mirror of
https://github.com/arsenetar/dupeguru-cocoa.git
synced 2026-01-22 14:41:40 +00:00
Convert cocoalib submodule to be in place.
This commit is contained in:
38
cocoalib/controllers/HSColumns.h
Normal file
38
cocoalib/controllers/HSColumns.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Python.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "PyColumns.h"
|
||||
|
||||
/*
|
||||
This structure is to define constants describing table columns (it's easier to maintain in code
|
||||
than in XIB files).
|
||||
*/
|
||||
typedef struct {
|
||||
NSString *attrname;
|
||||
NSUInteger defaultWidth;
|
||||
NSUInteger minWidth;
|
||||
NSUInteger maxWidth;
|
||||
BOOL sortable;
|
||||
Class cellClass;
|
||||
} HSColumnDef;
|
||||
|
||||
@interface HSColumns : HSGUIController {}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView;
|
||||
- (PyColumns *)model;
|
||||
- (NSTableView *)view;
|
||||
- (void)connectNotifications;
|
||||
- (void)disconnectNotifications;
|
||||
- (void)initializeColumns:(HSColumnDef *)columns;
|
||||
- (void)initializeColumnsFromModel:(HSColumnDef)columnModel;
|
||||
- (void)setColumnsAsReadOnly;
|
||||
- (void)restoreColumns;
|
||||
- (void)setColumn:(NSString *)colname visible:(BOOL)visible;
|
||||
@end
|
||||
198
cocoalib/controllers/HSColumns.m
Normal file
198
cocoalib/controllers/HSColumns.m
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSColumns.h"
|
||||
#import "Utils.h"
|
||||
#import "HSTableView.h" // To prevent warning on stopEditing
|
||||
|
||||
@implementation HSColumns
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:[PyColumns class]
|
||||
callbackClassName:@"ColumnsView" view:aTableView];
|
||||
[self connectNotifications];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self disconnectNotifications];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (PyColumns *)model
|
||||
{
|
||||
return (PyColumns *)model;
|
||||
}
|
||||
|
||||
- (NSTableView *)view
|
||||
{
|
||||
return (NSTableView *)view;
|
||||
}
|
||||
|
||||
- (void)connectNotifications
|
||||
{
|
||||
if ([self view] == nil) {
|
||||
/* This can happen if there something broken somewhere, and even though when that happens,
|
||||
it means that something serious is going on, the fact that we connect to all columnMoved:
|
||||
events messes thigs up even MORE. Don't connect when tableView is nil!
|
||||
*/
|
||||
return;
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnMoved:)
|
||||
name:NSTableViewColumnDidMoveNotification object:[self view]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnMoved:)
|
||||
name:NSOutlineViewColumnDidMoveNotification object:[self view]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnResized:)
|
||||
name:NSTableViewColumnDidResizeNotification object:[self view]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnResized:)
|
||||
name:NSOutlineViewColumnDidResizeNotification object:[self view]];
|
||||
}
|
||||
|
||||
- (void)disconnectNotifications
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
/*
|
||||
It is assumed, when this method is used, that the table/outline is empty *OR* that it is not
|
||||
defined in the column list.
|
||||
|
||||
Special note about NSOutlineView. You can use HSColumns on outline views, but you be aware that
|
||||
the "main" column (the one having the tree disclosure buttons) cannot be removed. Therefore,
|
||||
it has to be defined in the XIB and it must *not* be in column defs.
|
||||
*/
|
||||
- (void)initializeColumns:(HSColumnDef *)columns
|
||||
{
|
||||
/* We don't want default widths to overwrite stored with in the core code */
|
||||
[self disconnectNotifications];
|
||||
/* Translate the title of columns (needed for outlines) present already */
|
||||
for (NSTableColumn *c in [[self view] tableColumns]) {
|
||||
NSString *title = NSLocalizedStringFromTable([[c headerCell] stringValue], @"columns", @"");
|
||||
[[c headerCell] setStringValue:title];
|
||||
}
|
||||
NSUserDefaultsController *udc = [NSUserDefaultsController sharedUserDefaultsController];
|
||||
HSColumnDef *cdef = columns;
|
||||
while (cdef->attrname != nil) {
|
||||
if ([[self view] tableColumnWithIdentifier:cdef->attrname] != nil) {
|
||||
cdef++;
|
||||
continue;
|
||||
}
|
||||
NSTableColumn *c = [[[NSTableColumn alloc] initWithIdentifier:cdef->attrname] autorelease];
|
||||
[c setResizingMask:NSTableColumnUserResizingMask];
|
||||
/* If the column is not added right away, it causes glitches under 10.5 (minwidths instead of default widths) */
|
||||
[[self view] addTableColumn:c];
|
||||
NSString *title = [[self model] columnDisplay:cdef->attrname];
|
||||
[[c headerCell] setStringValue:title];
|
||||
if (cdef->sortable) {
|
||||
NSSortDescriptor *d = [[[NSSortDescriptor alloc] initWithKey:cdef->attrname ascending:YES] autorelease];
|
||||
[c setSortDescriptorPrototype:d];
|
||||
}
|
||||
[c setWidth:cdef->defaultWidth];
|
||||
[[self model] setColumn:cdef->attrname defaultWidth:cdef->defaultWidth];
|
||||
[c setMinWidth:cdef->minWidth];
|
||||
NSUInteger maxWidth = cdef->maxWidth;
|
||||
if (maxWidth == 0) {
|
||||
maxWidth = 0xffffff;
|
||||
}
|
||||
[c setMaxWidth:maxWidth];
|
||||
if (cdef->cellClass != nil) {
|
||||
id cell = [[[cdef->cellClass alloc] initTextCell:@""] autorelease];
|
||||
[cell setEditable:YES];
|
||||
[c setDataCell:cell];
|
||||
}
|
||||
[c bind:@"fontSize" toObject:udc withKeyPath:@"values.TableFontSize" options:nil];
|
||||
cdef++;
|
||||
}
|
||||
[self connectNotifications];
|
||||
}
|
||||
|
||||
/*
|
||||
Here, instead of having all our column defs, we have one column model, which we use to create
|
||||
our column defs using column names in [[self model] columnNamesInOrder].
|
||||
*/
|
||||
- (void)initializeColumnsFromModel:(HSColumnDef)columnModel
|
||||
{
|
||||
NSArray *colnames = [[self model] columnNamesInOrder];
|
||||
HSColumnDef *defs = (HSColumnDef *)malloc(([colnames count]+1)*sizeof(HSColumnDef));
|
||||
HSColumnDef *def = defs;
|
||||
for (NSString *colname in colnames) {
|
||||
def->attrname = colname;
|
||||
def->defaultWidth = columnModel.defaultWidth;
|
||||
def->minWidth = columnModel.minWidth;
|
||||
def->maxWidth = columnModel.maxWidth;
|
||||
def->sortable = columnModel.sortable;
|
||||
def->cellClass = columnModel.cellClass;
|
||||
def++;
|
||||
}
|
||||
def->attrname = nil; // Sentinel
|
||||
[self initializeColumns:defs];
|
||||
free(defs);
|
||||
}
|
||||
|
||||
- (void)setColumnsAsReadOnly
|
||||
{
|
||||
for (NSTableColumn *col in [[self view] tableColumns]) {
|
||||
[col setEditable:NO];
|
||||
}
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
- (void)columnMoved:(NSNotification *)notification
|
||||
{
|
||||
/* We only get this call after the move. Although there's "NSOldColumn" and "NSNewColumn",
|
||||
the old index is irrelevant since we have to find the moved column's name.
|
||||
*/
|
||||
NSInteger index = n2i([[notification userInfo] objectForKey:@"NSNewColumn"]);
|
||||
NSTableColumn *c = [[[self view] tableColumns] objectAtIndex:index];
|
||||
NSString *colName = [c identifier];
|
||||
[[self model] moveColumn:colName toIndex:index];
|
||||
}
|
||||
|
||||
- (void)columnResized:(NSNotification *)notification
|
||||
{
|
||||
NSTableColumn *c = [[notification userInfo] objectForKey:@"NSTableColumn"];
|
||||
[[self model] resizeColumn:[c identifier] toWidth:[c width]];
|
||||
}
|
||||
|
||||
/* Python --> Cocoa */
|
||||
- (void)restoreColumns
|
||||
{
|
||||
[self disconnectNotifications];
|
||||
NSArray *columnOrder = [[self model] columnNamesInOrder];
|
||||
for (NSInteger i=0; i<[columnOrder count]; i++) {
|
||||
NSString *colName = [columnOrder objectAtIndex:i];
|
||||
NSInteger index = [[self view] columnWithIdentifier:colName];
|
||||
if ((index != -1) && (index != i)) {
|
||||
[[self view] moveColumn:index toColumn:i];
|
||||
}
|
||||
}
|
||||
for (NSTableColumn *c in [[self view] tableColumns]) {
|
||||
NSInteger width = [[self model] columnWidth:[c identifier]];
|
||||
if (width > 0) {
|
||||
[c setWidth:width];
|
||||
}
|
||||
BOOL isVisible = [[self model] columnIsVisible:[c identifier]];
|
||||
[c setHidden:!isVisible];
|
||||
}
|
||||
[self connectNotifications];
|
||||
}
|
||||
|
||||
- (void)setColumn:(NSString *)colname visible:(BOOL)visible
|
||||
{
|
||||
NSTableColumn *col = [[self view] tableColumnWithIdentifier:colname];
|
||||
if (col == nil)
|
||||
return;
|
||||
if ([col isHidden] == !visible)
|
||||
return;
|
||||
if ([[self view] respondsToSelector:@selector(stopEditing)]) {
|
||||
[(id)[self view] stopEditing];
|
||||
}
|
||||
[col setHidden:!visible];
|
||||
}
|
||||
@end
|
||||
25
cocoalib/controllers/HSComboBox.h
Normal file
25
cocoalib/controllers/HSComboBox.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "PySelectableList.h"
|
||||
|
||||
@interface HSComboBox : HSGUIController <NSComboBoxDataSource>
|
||||
{
|
||||
NSArray *items;
|
||||
}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSComboBox *)aView;
|
||||
- (NSComboBox *)view;
|
||||
- (void)setView:(NSComboBox *)aComboboxView;
|
||||
- (PySelectableList *)model;
|
||||
|
||||
- (void)comboboxViewSelectionChanged;
|
||||
- (void)refresh;
|
||||
- (void)updateSelection;
|
||||
@end
|
||||
119
cocoalib/controllers/HSComboBox.m
Normal file
119
cocoalib/controllers/HSComboBox.m
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSComboBox.h"
|
||||
#import "HSPyUtil.h"
|
||||
|
||||
@implementation HSComboBox
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSComboBox *)aView
|
||||
{
|
||||
PySelectableList *m = [[PySelectableList alloc] initWithModel:aPyRef];
|
||||
self = [super initWithModel:m];
|
||||
[m bindCallback:createCallback(@"SelectableListView", self)];
|
||||
[m release];
|
||||
[self setView:aView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[self view] setTarget:nil];
|
||||
[[self view] setDataSource:nil];
|
||||
[items release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSComboBox *)view
|
||||
{
|
||||
return (NSComboBox *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSComboBox *)aComboboxView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setDataSource:nil];
|
||||
[[self view] setTarget:nil];
|
||||
}
|
||||
[super setView:aComboboxView];
|
||||
if (aComboboxView != nil) {
|
||||
[aComboboxView setUsesDataSource:YES];
|
||||
[aComboboxView setDataSource:self];
|
||||
[aComboboxView setAction:@selector(comboboxViewSelectionChanged)];
|
||||
[aComboboxView setTarget:self];
|
||||
/* This is required for the combobox to send its action whenever it's changed. Normally, it's
|
||||
already set, but then the combobox is created programmatically (xibless), it's not. We
|
||||
make sure it is here.
|
||||
*/
|
||||
[[aComboboxView cell] setSendsActionOnEndEditing:YES];
|
||||
[self refresh];
|
||||
}
|
||||
}
|
||||
|
||||
- (PySelectableList *)model
|
||||
{
|
||||
return (PySelectableList *)model;
|
||||
}
|
||||
|
||||
- (void)comboboxViewSelectionChanged
|
||||
{
|
||||
NSInteger index = [[self view] indexOfSelectedItem];
|
||||
if (index >= 0) {
|
||||
[[self model] selectIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
/* data source */
|
||||
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index
|
||||
{
|
||||
if (index < 0) {
|
||||
return nil;
|
||||
}
|
||||
return [items objectAtIndex:index];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
|
||||
{
|
||||
return [items count];
|
||||
}
|
||||
|
||||
- (NSUInteger)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)aString
|
||||
{
|
||||
NSInteger index = [[self model] searchByPrefix:aString];
|
||||
if (index >= 0) {
|
||||
return index;
|
||||
}
|
||||
else {
|
||||
return NSNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)uncompletedString
|
||||
{
|
||||
NSInteger index = [[self model] searchByPrefix:uncompletedString];
|
||||
if (index >= 0) {
|
||||
return [items objectAtIndex:index];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/* model --> view */
|
||||
- (void)refresh
|
||||
{
|
||||
[items release];
|
||||
items = [[[self model] items] retain];
|
||||
[[self view] reloadData];
|
||||
[self updateSelection];
|
||||
}
|
||||
|
||||
- (void)updateSelection
|
||||
{
|
||||
[[self view] selectItemAtIndex:[[self model] selectedIndex]];
|
||||
}
|
||||
@end
|
||||
23
cocoalib/controllers/HSGUIController.h
Normal file
23
cocoalib/controllers/HSGUIController.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "PyGUIObject.h"
|
||||
|
||||
@interface HSGUIController : NSObject
|
||||
{
|
||||
PyGUIObject *model;
|
||||
NSView *view;
|
||||
}
|
||||
- (id)initWithModel:(PyGUIObject *)aPy;
|
||||
- (id)initWithModel:(PyGUIObject *)aPy view:(NSView *)aView;
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSView *)aView;
|
||||
- (PyGUIObject *)model;
|
||||
- (NSView *)view;
|
||||
- (void)setView:(NSView *)aView;
|
||||
@end
|
||||
62
cocoalib/controllers/HSGUIController.m
Normal file
62
cocoalib/controllers/HSGUIController.m
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSGUIController.h"
|
||||
#import "HSPyUtil.h"
|
||||
|
||||
@implementation HSGUIController
|
||||
- (id)initWithModel:(PyGUIObject *)aModel
|
||||
{
|
||||
self = [super init];
|
||||
model = [aModel retain];
|
||||
view = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithModel:(PyGUIObject *)aModel view:(NSView *)aView
|
||||
{
|
||||
self = [super init];
|
||||
model = [aModel retain];
|
||||
[self setView:aView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSView *)aView
|
||||
{
|
||||
PyGUIObject *m = [[aWrapperClass alloc] initWithModel:aPyRef];
|
||||
self = [self initWithModel:m view:aView];
|
||||
[m bindCallback:createCallback(aCallbackClassName, self)];
|
||||
[m release];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// NSLog([NSString stringWithFormat:@"%@ dealloc",[[self class] description]]);
|
||||
[self setView:nil];
|
||||
[model free];
|
||||
[model release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (PyGUIObject *)model
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
- (NSView *)view
|
||||
{
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSView *)aView
|
||||
{
|
||||
[view release];
|
||||
view = [aView retain];
|
||||
}
|
||||
@end
|
||||
44
cocoalib/controllers/HSOutline.h
Normal file
44
cocoalib/controllers/HSOutline.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "HSOutlineView.h"
|
||||
#import "PyOutline.h"
|
||||
#import "NSIndexPathAdditions.h"
|
||||
|
||||
@interface HSOutline : HSGUIController <HSOutlineViewDelegate, NSOutlineViewDataSource> {
|
||||
NSMutableDictionary *itemData;
|
||||
NSMutableSet *itemRetainer;
|
||||
}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(HSOutlineView *)aView;
|
||||
- (PyOutline *)model;
|
||||
- (HSOutlineView *)view;
|
||||
|
||||
/* Public */
|
||||
- (void)refresh;
|
||||
- (NSIndexPath *)selectedIndexPath;
|
||||
- (NSArray *)selectedIndexPaths;
|
||||
- (NSString *)dataForCopyToPasteboard;
|
||||
- (void)startEditing;
|
||||
- (void)stopEditing;
|
||||
- (void)updateSelection;
|
||||
- (void)expandItem:(NSIndexPath *)item;
|
||||
- (NSIndexPath *)internalizedPath:(NSIndexPath *)path;
|
||||
|
||||
/* Caching */
|
||||
- (id)property:(NSString *)property valueAtPath:(NSIndexPath *)path;
|
||||
- (void)setProperty:(NSString *)property value:(id)value atPath:(NSIndexPath *)path;
|
||||
- (NSString *)stringProperty:(NSString *)property valueAtPath:(NSIndexPath *)path;
|
||||
- (void)setStringProperty:(NSString *)property value:(NSString *)value atPath:(NSIndexPath *)path;
|
||||
- (BOOL)boolProperty:(NSString *)property valueAtPath:(NSIndexPath *)path;
|
||||
- (void)setBoolProperty:(NSString *)property value:(BOOL)value atPath:(NSIndexPath *)path;
|
||||
- (NSInteger)intProperty:(NSString *)property valueAtPath:(NSIndexPath *)path;
|
||||
- (void)setIntProperty:(NSString *)property value:(int)value atPath:(NSIndexPath *)path;
|
||||
- (void)refreshItemAtPath:(NSIndexPath *)path;
|
||||
@end
|
||||
286
cocoalib/controllers/HSOutline.m
Normal file
286
cocoalib/controllers/HSOutline.m
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSOutline.h"
|
||||
#import "Utils.h"
|
||||
|
||||
#define CHILDREN_COUNT_PROPERTY @"children_count"
|
||||
|
||||
@implementation HSOutline
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(HSOutlineView *)aView
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aView];
|
||||
itemData = [[NSMutableDictionary dictionary] retain];
|
||||
/* Dictionaries don't retain its keys because it copies them. Our items are NSIndexPath and when
|
||||
an index path has the same value, it's the same instance. Before OS X 10.7, all these instances
|
||||
stayed in memory, so we didn't need to worry about retaining them. Hoever, it seems now that
|
||||
index path instances are sometimes released. Oops. So, we now need to retain our index path
|
||||
instances and that's why we use itemRetainer.
|
||||
|
||||
In fact, it seems that unlike what the doc says, it's not true that two index paths with the
|
||||
same value will always be the same instance.
|
||||
*/
|
||||
itemRetainer = [[NSMutableSet set] retain];
|
||||
if (([[self view] outlineTableColumn] == nil) && ([[[self view] tableColumns] count] > 0)) {
|
||||
[[self view] setOutlineTableColumn:[[[self view] tableColumns] objectAtIndex:0]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[itemData release];
|
||||
[itemRetainer release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (HSOutlineView *)view
|
||||
{
|
||||
return (HSOutlineView *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(HSOutlineView *)aOutlineView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setDataSource:nil];
|
||||
[[self view] setDelegate:nil];
|
||||
}
|
||||
[super setView:aOutlineView];
|
||||
if (aOutlineView != nil) {
|
||||
[aOutlineView setDataSource:self];
|
||||
[aOutlineView setDelegate:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (PyOutline *)model
|
||||
{
|
||||
return (PyOutline *)model;
|
||||
}
|
||||
|
||||
/* Private */
|
||||
- (void)setPySelection
|
||||
{
|
||||
NSMutableArray *paths = [NSMutableArray array];
|
||||
NSIndexSet *indexes = [[self view] selectedRowIndexes];
|
||||
NSInteger i = [indexes firstIndex];
|
||||
while (i != NSNotFound) {
|
||||
NSIndexPath *path = [[self view] itemAtRow:i];
|
||||
[paths addObject:p2a(path)];
|
||||
i = [indexes indexGreaterThanIndex:i];
|
||||
}
|
||||
[[self model] setSelectedPaths:paths];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)internalizedPath:(NSIndexPath *)path
|
||||
{
|
||||
/* Because NSIndexPath stopped guaranteeing that the same paths always were represented by the
|
||||
same instances, we have to make sure, when we manipulate paths, that we manipulate the same
|
||||
instances as those that were given by outlineView:child:ofItem:
|
||||
*/
|
||||
NSIndexPath *result = [itemRetainer member:path];
|
||||
if (result == nil) {
|
||||
result = path;
|
||||
[itemData setObject:[NSMutableDictionary dictionary] forKey:result];
|
||||
[itemRetainer addObject:result];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Public */
|
||||
- (void)refresh
|
||||
{
|
||||
[itemData removeAllObjects];
|
||||
// We can't get rid of our instances just yet, we have to wait until after reloadData
|
||||
NSSet *oldRetainer = itemRetainer;
|
||||
itemRetainer = [[NSMutableSet set] retain];
|
||||
[[self view] setDelegate:nil];
|
||||
[[self view] reloadData];
|
||||
[[self view] setDelegate:self];
|
||||
/* Item retainer and releasing
|
||||
|
||||
In theory, [oldRetainer release] should work, but in practice, doing so causes occasional
|
||||
crashes during drag & drop, which I guess keep the reference of an item a bit longer than it
|
||||
should. This is why we autorelease here. See #354.
|
||||
*/
|
||||
[oldRetainer autorelease];
|
||||
[self updateSelection];
|
||||
}
|
||||
|
||||
- (NSArray *)selectedIndexPaths
|
||||
{
|
||||
NSArray *arrayPaths = [[self model] selectedPaths];
|
||||
NSMutableArray *result = [NSMutableArray array];
|
||||
for (NSArray *arrayPath in arrayPaths) {
|
||||
[result addObject:[self internalizedPath:a2p(arrayPath)]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)startEditing
|
||||
{
|
||||
[[self view] startEditing];
|
||||
}
|
||||
|
||||
- (void)stopEditing
|
||||
{
|
||||
[[self view] stopEditing];
|
||||
}
|
||||
|
||||
- (void)updateSelection
|
||||
{
|
||||
[[self view] updateSelection];
|
||||
}
|
||||
|
||||
- (void)expandItem:(NSIndexPath *)item
|
||||
{
|
||||
[[self view] ensureExpanded:item];
|
||||
}
|
||||
|
||||
/* Caching */
|
||||
- (id)property:(NSString *)property valueAtPath:(NSIndexPath *)path
|
||||
{
|
||||
NSMutableDictionary *props = [itemData objectForKey:path];
|
||||
id value = [props objectForKey:property];
|
||||
if (value == nil) {
|
||||
value = [[self model] property:property valueAtPath:p2a(path)];
|
||||
if (value == nil) {
|
||||
value = [NSNull null];
|
||||
}
|
||||
[props setObject:value forKey:property];
|
||||
}
|
||||
if (value == [NSNull null]) {
|
||||
value = nil;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
- (void)setProperty:(NSString *)property value:(id)value atPath:(NSIndexPath *)path
|
||||
{
|
||||
NSMutableDictionary *props = [itemData objectForKey:path];
|
||||
[props removeObjectForKey:property];
|
||||
[[self model] setProperty:property value:value atPath:p2a(path)];
|
||||
}
|
||||
|
||||
- (NSString *)stringProperty:(NSString *)property valueAtPath:(NSIndexPath *)path
|
||||
{
|
||||
return [self property:property valueAtPath:path];
|
||||
}
|
||||
|
||||
- (void)setStringProperty:(NSString *)property value:(NSString *)value atPath:(NSIndexPath *)path
|
||||
{
|
||||
[self setProperty:property value:value atPath:path];
|
||||
}
|
||||
|
||||
- (BOOL)boolProperty:(NSString *)property valueAtPath:(NSIndexPath *)path
|
||||
{
|
||||
NSNumber *value = [self property:property valueAtPath:path];
|
||||
return [value boolValue];
|
||||
}
|
||||
|
||||
- (void)setBoolProperty:(NSString *)property value:(BOOL)value atPath:(NSIndexPath *)path
|
||||
{
|
||||
[self setProperty:property value:[NSNumber numberWithBool:value] atPath:path];
|
||||
}
|
||||
|
||||
- (NSInteger)intProperty:(NSString *)property valueAtPath:(NSIndexPath *)path
|
||||
{
|
||||
NSNumber *value = [self property:property valueAtPath:path];
|
||||
return [value intValue];
|
||||
}
|
||||
|
||||
- (void)setIntProperty:(NSString *)property value:(int)value atPath:(NSIndexPath *)path
|
||||
{
|
||||
[self setProperty:property value:[NSNumber numberWithInt:value] atPath:path];
|
||||
}
|
||||
|
||||
- (void)refreshItemAtPath:(NSIndexPath *)path
|
||||
{
|
||||
NSMutableDictionary *props = [itemData objectForKey:path];
|
||||
[props removeAllObjects];
|
||||
}
|
||||
|
||||
/* NSOutlineView data source */
|
||||
|
||||
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
return [self intProperty:CHILDREN_COUNT_PROPERTY valueAtPath:(NSIndexPath *)item];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
|
||||
{
|
||||
NSIndexPath *parent = item;
|
||||
NSIndexPath *path = parent == nil ? [NSIndexPath indexPathWithIndex:index] : [parent indexPathByAddingIndex:index];
|
||||
return [self internalizedPath:path];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)theOutlineView isItemExpandable:(id)item
|
||||
{
|
||||
return [self outlineView:[self view] numberOfChildrenOfItem:item] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)column item:(id)item
|
||||
{
|
||||
return [[self model] canEditProperty:[column identifier] atPath:p2a((NSIndexPath *)item)];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)column byItem:(id)item
|
||||
{
|
||||
return [self property:[column identifier] valueAtPath:(NSIndexPath *)item];
|
||||
}
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)value forTableColumn:(NSTableColumn *)column byItem:(id)item
|
||||
{
|
||||
[self setProperty:[column identifier] value:value atPath:(NSIndexPath *)item];
|
||||
}
|
||||
|
||||
/* We need to change the model selection at both IsChanging and DidChange. We need to set the
|
||||
model selection at IsChanging before of the arrow clicking. The action launched by this little arrow
|
||||
is performed before DidChange. However, when using the arrow to change the selection, IsChanging is
|
||||
never called
|
||||
*/
|
||||
- (void)outlineViewSelectionIsChanging:(NSNotification *)notification
|
||||
{
|
||||
[self setPySelection];
|
||||
}
|
||||
|
||||
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[self setPySelection];
|
||||
}
|
||||
|
||||
/* HSOutlineView delegate */
|
||||
- (NSIndexPath *)selectedIndexPath
|
||||
{
|
||||
NSArray *paths = [self selectedIndexPaths];
|
||||
if ([paths count] > 0) {
|
||||
return [paths objectAtIndex:0];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)dataForCopyToPasteboard
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)outlineViewDidEndEditing:(HSOutlineView *)outlineView
|
||||
{
|
||||
[[self model] saveEdits];
|
||||
}
|
||||
|
||||
- (void)outlineViewWasDoubleClicked:(HSOutlineView *)outlineView
|
||||
{
|
||||
}
|
||||
|
||||
- (void)outlineViewCancelsEdition:(HSOutlineView *)outlineView
|
||||
{
|
||||
[[self model] cancelEdits];
|
||||
}
|
||||
@end
|
||||
23
cocoalib/controllers/HSPopUpList.h
Normal file
23
cocoalib/controllers/HSPopUpList.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Python.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "PySelectableList.h"
|
||||
|
||||
@interface HSPopUpList : HSGUIController {}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef popupView:(NSPopUpButton *)aPopupView;
|
||||
- (NSPopUpButton *)view;
|
||||
- (void)setView:(NSPopUpButton *)aPopupView;
|
||||
- (PySelectableList *)model;
|
||||
|
||||
- (void)popupViewSelectionChanged;
|
||||
- (void)refresh;
|
||||
- (void)updateSelection;
|
||||
@end
|
||||
60
cocoalib/controllers/HSPopUpList.m
Normal file
60
cocoalib/controllers/HSPopUpList.m
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSPopUpList.h"
|
||||
#import "Utils.h"
|
||||
|
||||
@implementation HSPopUpList
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef popupView:(NSPopUpButton *)aPopupView
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:[PySelectableList class]
|
||||
callbackClassName:@"SelectableListView" view:aPopupView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSPopUpButton *)view
|
||||
{
|
||||
return (NSPopUpButton *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSPopUpButton *)aPopupView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setTarget:nil];
|
||||
}
|
||||
[super setView:aPopupView];
|
||||
if (aPopupView != nil) {
|
||||
[aPopupView setAction:@selector(popupViewSelectionChanged)];
|
||||
[aPopupView setTarget:self];
|
||||
[self refresh];
|
||||
}
|
||||
}
|
||||
|
||||
- (PySelectableList *)model
|
||||
{
|
||||
return (PySelectableList *)model;
|
||||
}
|
||||
|
||||
- (void)popupViewSelectionChanged
|
||||
{
|
||||
[[self model] selectIndex:[[self view] indexOfSelectedItem]];
|
||||
}
|
||||
|
||||
/* model --> view */
|
||||
- (void)refresh
|
||||
{
|
||||
[[self view] removeAllItems];
|
||||
[[self view] addItemsWithTitles:[[self model] items]];
|
||||
[self updateSelection];
|
||||
}
|
||||
|
||||
- (void)updateSelection
|
||||
{
|
||||
[[self view] selectItemAtIndex:[[self model] selectedIndex]];
|
||||
}
|
||||
@end
|
||||
30
cocoalib/controllers/HSProgressWindow.h
Normal file
30
cocoalib/controllers/HSProgressWindow.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "HSTextField.h"
|
||||
#import "Worker.h"
|
||||
#import "PyProgressWindow.h"
|
||||
|
||||
@interface HSProgressWindow : HSGUIController <Worker>
|
||||
{
|
||||
NSInteger progress;
|
||||
HSTextField *jobdescTextField;
|
||||
HSTextField *progressdescTextField;
|
||||
NSWindow *parentWindow;
|
||||
}
|
||||
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSView *)aView;
|
||||
- (PyProgressWindow *)model;
|
||||
- (void)setParentWindow:(NSWindow *)aParentWindow;
|
||||
|
||||
- (void)setProgress:(NSInteger)aProgress;
|
||||
- (void)showWindow;
|
||||
- (void)closeWindow;
|
||||
@end
|
||||
79
cocoalib/controllers/HSProgressWindow.m
Normal file
79
cocoalib/controllers/HSProgressWindow.m
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSProgressWindow.h"
|
||||
#import "ProgressController.h"
|
||||
#import "Utils.h"
|
||||
|
||||
@implementation HSProgressWindow
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSView *)aView
|
||||
{
|
||||
self = [self initWithPyRef:aPyRef wrapperClass:[PyProgressWindow class] callbackClassName:@"ProgressWindowView" view:aView];
|
||||
[[ProgressController mainProgressController] setWorker:self];
|
||||
jobdescTextField = [[HSTextField alloc] initWithPyRef:[[self model] jobdescTextField] view:[[ProgressController mainProgressController] descText]];
|
||||
progressdescTextField = [[HSTextField alloc] initWithPyRef:[[self model] progressdescTextField] view:[[ProgressController mainProgressController] statusText]];
|
||||
parentWindow = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (PyProgressWindow *)model
|
||||
{
|
||||
return (PyProgressWindow *)model;
|
||||
}
|
||||
|
||||
/* Public */
|
||||
- (void)setParentWindow:(NSWindow *)aParentWindow
|
||||
{
|
||||
parentWindow = aParentWindow;
|
||||
}
|
||||
|
||||
- (void)setProgress:(NSInteger)aProgress
|
||||
{
|
||||
progress = aProgress;
|
||||
}
|
||||
|
||||
- (void)showWindow
|
||||
{
|
||||
if (parentWindow != nil) {
|
||||
[[ProgressController mainProgressController] showSheetForParent:parentWindow];
|
||||
}
|
||||
else {
|
||||
[[ProgressController mainProgressController] show];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeWindow
|
||||
{
|
||||
[[ProgressController mainProgressController] hide];
|
||||
}
|
||||
|
||||
/* Worker */
|
||||
|
||||
- (NSNumber *)getJobProgress
|
||||
{
|
||||
[[self model] pulse];
|
||||
return [NSNumber numberWithInt:progress];
|
||||
}
|
||||
|
||||
- (NSString *)getJobDesc
|
||||
{
|
||||
// Our desc label is updated independently.
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)cancelJob
|
||||
{
|
||||
[[self model] cancel];
|
||||
}
|
||||
|
||||
- (void)jobCompleted:(NSString *)jobid
|
||||
{
|
||||
// With the new hscommon.gui.progress_window, this call is done from within the core. Do nothing.
|
||||
}
|
||||
|
||||
@end
|
||||
24
cocoalib/controllers/HSSelectableList.h
Normal file
24
cocoalib/controllers/HSSelectableList.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "PySelectableList.h"
|
||||
|
||||
@interface HSSelectableList : HSGUIController <NSTableViewDelegate, NSTableViewDataSource>
|
||||
{
|
||||
NSArray *items;
|
||||
}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView;
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView;
|
||||
- (NSTableView *)view;
|
||||
- (void)setView:(NSTableView *)aTableView;
|
||||
- (PySelectableList *)model;
|
||||
|
||||
- (void)refresh;
|
||||
@end
|
||||
107
cocoalib/controllers/HSSelectableList.m
Normal file
107
cocoalib/controllers/HSSelectableList.m
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSSelectableList.h"
|
||||
#import "Utils.h"
|
||||
|
||||
@implementation HSSelectableList
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView;
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aTableView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView
|
||||
{
|
||||
self = [self initWithPyRef:aPyRef wrapperClass:[PySelectableList class] callbackClassName:@"SelectableListView" view:aTableView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[items release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (PySelectableList *)model
|
||||
{
|
||||
return (PySelectableList *)model;
|
||||
}
|
||||
|
||||
- (NSTableView *)view
|
||||
{
|
||||
return (NSTableView *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSTableView *)aTableView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setDataSource:nil];
|
||||
[[self view] setDelegate:nil];
|
||||
}
|
||||
[super setView:aTableView];
|
||||
if (aTableView != nil) {
|
||||
[aTableView setDataSource:self];
|
||||
[aTableView setDelegate:self];
|
||||
[self refresh];
|
||||
}
|
||||
}
|
||||
|
||||
/* Private */
|
||||
- (void)setPySelection
|
||||
{
|
||||
NSArray *selection = [Utils indexSet2Array:[[self view] selectedRowIndexes]];
|
||||
NSArray *pyselection = [[self model] selectedIndexes];
|
||||
if (![selection isEqualTo:pyselection]) {
|
||||
[[self model] selectIndexes:selection];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setViewSelection
|
||||
{
|
||||
NSIndexSet *selection = [Utils array2IndexSet:[[self model] selectedIndexes]];
|
||||
[[self view] selectRowIndexes:selection byExtendingSelection:NO];
|
||||
}
|
||||
|
||||
/* Data source */
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||||
{
|
||||
return [items count];
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row
|
||||
{
|
||||
// Cocoa's typeselect mechanism can call us with an out-of-range row
|
||||
if (row >= [items count]) {
|
||||
return @"";
|
||||
}
|
||||
return [items objectAtIndex:row];
|
||||
}
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[self setPySelection];
|
||||
}
|
||||
|
||||
/* Public */
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
// If we just deleted the last item, we want to update the selection before we reload
|
||||
[items release];
|
||||
items = [[[self model] items] retain];
|
||||
[[self view] reloadData];
|
||||
[self setViewSelection];
|
||||
}
|
||||
|
||||
- (void)updateSelection
|
||||
{
|
||||
NSIndexSet *selection = [NSIndexSet indexSetWithIndex:[[self model] selectedIndex]];
|
||||
[[self view] selectRowIndexes:selection byExtendingSelection:NO];
|
||||
}
|
||||
@end
|
||||
32
cocoalib/controllers/HSTable.h
Normal file
32
cocoalib/controllers/HSTable.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "HSColumns.h"
|
||||
#import "PyTable.h"
|
||||
|
||||
@interface HSTable : HSGUIController <NSTableViewDelegate, NSTableViewDataSource>
|
||||
{
|
||||
HSColumns *columns;
|
||||
}
|
||||
- (id)initWithModel:(PyTable *)aModel tableView:(NSTableView *)aTableView;
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView;
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView;
|
||||
|
||||
/* Virtual */
|
||||
- (PyTable *)model;
|
||||
- (NSTableView *)view;
|
||||
- (void)setView:(NSTableView *)aTableView;
|
||||
|
||||
/* Public */
|
||||
- (HSColumns *)columns;
|
||||
- (void)refresh;
|
||||
- (void)showSelectedRow;
|
||||
- (void)updateSelection;
|
||||
@end
|
||||
136
cocoalib/controllers/HSTable.m
Normal file
136
cocoalib/controllers/HSTable.m
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSTable.h"
|
||||
#import "Utils.h"
|
||||
|
||||
@implementation HSTable
|
||||
- (id)initWithModel:(PyTable *)aModel tableView:(NSTableView *)aTableView
|
||||
{
|
||||
self = [super initWithModel:aModel view:aTableView];
|
||||
columns = [[HSColumns alloc] initWithPyRef:[[self model] columns] tableView:aTableView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aTableView];
|
||||
columns = [[HSColumns alloc] initWithPyRef:[[self model] columns] tableView:aTableView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView
|
||||
{
|
||||
return [self initWithPyRef:aPyRef wrapperClass:[PyTable class] callbackClassName:@"TableView" view:aTableView];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[columns release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* Private */
|
||||
- (void)setPySelection
|
||||
{
|
||||
NSArray *selection = [Utils indexSet2Array:[[self view] selectedRowIndexes]];
|
||||
NSArray *pyselection = [[self model] selectedRows];
|
||||
if (![selection isEqualTo:pyselection])
|
||||
[[self model] selectRows:selection];
|
||||
}
|
||||
|
||||
- (void)setViewSelection
|
||||
{
|
||||
NSIndexSet *selection = [Utils array2IndexSet:[[self model] selectedRows]];
|
||||
[[self view] selectRowIndexes:selection byExtendingSelection:NO];
|
||||
}
|
||||
|
||||
/* HSGUIController */
|
||||
- (PyTable *)model
|
||||
{
|
||||
return (PyTable *)model;
|
||||
}
|
||||
|
||||
- (NSTableView *)view
|
||||
{
|
||||
return (NSTableView *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSTableView *)aTableView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setDataSource:nil];
|
||||
[[self view] setDelegate:nil];
|
||||
}
|
||||
[super setView:aTableView];
|
||||
if (aTableView != nil) {
|
||||
[aTableView setDataSource:self];
|
||||
[aTableView setDelegate:self];
|
||||
}
|
||||
}
|
||||
|
||||
/* Data source */
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||||
{
|
||||
return [[self model] numberOfRows];
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row
|
||||
{
|
||||
// Cocoa's typeselect mechanism can call us with an out-of-range row
|
||||
if (row >= [[self model] numberOfRows]) {
|
||||
return @"";
|
||||
}
|
||||
return [[self model] valueForColumn:[column identifier] row:row];
|
||||
}
|
||||
|
||||
/* NSTableView Delegate */
|
||||
- (void)tableView:(NSTableView *)aTableView didClickTableColumn:(NSTableColumn *)column
|
||||
{
|
||||
if ([[aTableView sortDescriptors] count] == 0) {
|
||||
return;
|
||||
}
|
||||
NSSortDescriptor *sd = [[aTableView sortDescriptors] objectAtIndex:0];
|
||||
[[self model] sortByColumn:[sd key] desc:![sd ascending]];
|
||||
}
|
||||
|
||||
// See HSOutline.outlineViewSelectionIsChanging: to know why we update selection in both notifs
|
||||
- (void)tableViewSelectionIsChanging:(NSNotification *)notification
|
||||
{
|
||||
[self setPySelection];
|
||||
}
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[self setPySelection];
|
||||
}
|
||||
|
||||
/* Public */
|
||||
- (HSColumns *)columns
|
||||
{
|
||||
return columns;
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
// If we just deleted the last item, we want to update the selection before we reload
|
||||
[self setViewSelection];
|
||||
[[self view] reloadData];
|
||||
[self setViewSelection];
|
||||
}
|
||||
|
||||
- (void)showSelectedRow
|
||||
{
|
||||
[[self view] scrollRowToVisible:[[self view] selectedRow]];
|
||||
}
|
||||
|
||||
- (void)updateSelection
|
||||
{
|
||||
[self setViewSelection];
|
||||
}
|
||||
@end
|
||||
21
cocoalib/controllers/HSTextField.h
Normal file
21
cocoalib/controllers/HSTextField.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Python.h>
|
||||
#import "HSGUIController.h"
|
||||
#import "PyTextField.h"
|
||||
|
||||
@interface HSTextField : HSGUIController <NSTextFieldDelegate> {}
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aView;
|
||||
- (NSTextField *)view;
|
||||
- (void)setView:(NSTextField *)aView;
|
||||
- (PyTextField *)model;
|
||||
|
||||
- (void)refresh;
|
||||
@end
|
||||
53
cocoalib/controllers/HSTextField.m
Normal file
53
cocoalib/controllers/HSTextField.m
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
||||
|
||||
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
||||
which should be included with this package. The terms are also available at
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*/
|
||||
|
||||
#import "HSTextField.h"
|
||||
#import "Utils.h"
|
||||
|
||||
@implementation HSTextField
|
||||
- (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aView
|
||||
{
|
||||
self = [super initWithPyRef:aPyRef wrapperClass:[PyTextField class]
|
||||
callbackClassName:@"GUIObjectView" view:aView];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSTextField *)view
|
||||
{
|
||||
return (NSTextField *)view;
|
||||
}
|
||||
|
||||
- (void)setView:(NSTextField *)aView
|
||||
{
|
||||
if ([self view] != nil) {
|
||||
[[self view] setDelegate:nil];
|
||||
}
|
||||
[super setView:aView];
|
||||
if (aView != nil) {
|
||||
[aView setDelegate:self];
|
||||
[self refresh];
|
||||
}
|
||||
}
|
||||
|
||||
- (PyTextField *)model
|
||||
{
|
||||
return (PyTextField *)model;
|
||||
}
|
||||
|
||||
/* Delegate */
|
||||
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
|
||||
{
|
||||
[[self model] setText:[[self view] stringValue]];
|
||||
}
|
||||
|
||||
/* model --> view */
|
||||
- (void)refresh
|
||||
{
|
||||
[[self view] setStringValue:[[self model] text]];
|
||||
}
|
||||
@end
|
||||
Reference in New Issue
Block a user