1
0
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:
2020-12-29 19:46:14 -06:00
parent ce0bb606b2
commit 99b98db93a
81 changed files with 5258 additions and 4 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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