From 5ac1d383d2a89d22fbf54d688d64bf6a1036df6b Mon Sep 17 00:00:00 2001 From: Alex Merry Date: Mon, 17 Dec 2012 17:51:10 +0000 Subject: Factor out properties pane from properties window PropertiesWindow is now ContextWindow. Preparing for putting more stuff in this window. --- tikzit/src/Makefile.am | 3 +- tikzit/src/gtk/Application.h | 8 +- tikzit/src/gtk/Application.m | 19 +- tikzit/src/gtk/ContextWindow.h | 48 +++ tikzit/src/gtk/ContextWindow.m | 151 +++++++++ tikzit/src/gtk/Menu.m | 10 +- tikzit/src/gtk/PropertiesPane.h | 73 +++++ tikzit/src/gtk/PropertiesPane.m | 638 +++++++++++++++++++++++++++++++++++++ tikzit/src/gtk/PropertiesWindow.h | 68 ---- tikzit/src/gtk/PropertiesWindow.m | 650 -------------------------------------- 10 files changed, 931 insertions(+), 737 deletions(-) create mode 100644 tikzit/src/gtk/ContextWindow.h create mode 100644 tikzit/src/gtk/ContextWindow.m create mode 100644 tikzit/src/gtk/PropertiesPane.h create mode 100644 tikzit/src/gtk/PropertiesPane.m delete mode 100644 tikzit/src/gtk/PropertiesWindow.h delete mode 100644 tikzit/src/gtk/PropertiesWindow.m diff --git a/tikzit/src/Makefile.am b/tikzit/src/Makefile.am index 276723d..6890928 100644 --- a/tikzit/src/Makefile.am +++ b/tikzit/src/Makefile.am @@ -30,6 +30,7 @@ tikzit_SOURCES = gtk/Application.m \ gtk/ColorRGB+IntegerListStorage.m \ gtk/ColorRGB+Gtk.m \ gtk/Configuration.m \ + gtk/ContextWindow.m \ gtk/CreateEdgeTool.m \ gtk/CreateNodeTool.m \ gtk/Edge+Render.m \ @@ -54,7 +55,7 @@ tikzit_SOURCES = gtk/Application.m \ gtk/NSError+Glib.m \ gtk/NSFileManager+Glib.m \ gtk/NSString+Glib.m \ - gtk/PropertiesWindow.m \ + gtk/PropertiesPane.m \ gtk/PropertyListEditor.m \ gtk/RecentManager.m \ gtk/SelectTool.m \ diff --git a/tikzit/src/gtk/Application.h b/tikzit/src/gtk/Application.h index eb9dbbf..b364c5e 100644 --- a/tikzit/src/gtk/Application.h +++ b/tikzit/src/gtk/Application.h @@ -20,10 +20,10 @@ @class Application; @class Configuration; +@class ContextWindow; @class Preambles; @class PreambleEditor; @class PreviewWindow; -@class PropertiesWindow; @class SettingsDialog; @class StyleManager; @class TikzDocument; @@ -50,7 +50,7 @@ extern Application* app; ToolBox *toolBox; PreambleEditor *preambleWindow; PreviewWindow *previewWindow; - PropertiesWindow *propertiesWindow; + ContextWindow *contextWindow; SettingsDialog *settingsDialog; // the open windows (array of Window*) @@ -131,9 +131,9 @@ extern Application* app; */ - (void) showPreamblesEditor; /** - * Show the property editor pane + * Show the context-aware window */ -- (void) showPropertyEditor; +- (void) showContextWindow; /** * Show or update the preview window. */ diff --git a/tikzit/src/gtk/Application.m b/tikzit/src/gtk/Application.m index a7f1824..cdf4b4e 100644 --- a/tikzit/src/gtk/Application.m +++ b/tikzit/src/gtk/Application.m @@ -21,7 +21,7 @@ #import "EdgeStylesModel.h" #import "NodeStylesModel.h" #import "PreambleEditor.h" -#import "PropertiesWindow.h" +#import "ContextWindow.h" #import "Shape.h" #import "StyleManager.h" #import "StyleManager+Storage.h" @@ -134,8 +134,9 @@ Application* app = nil; object:toolBox]; [toolBox show]; - propertiesWindow = [[PropertiesWindow alloc] init]; - [propertiesWindow loadConfiguration:configFile]; + contextWindow = [[ContextWindow alloc] initWithNodeStylesModel:nsm + andEdgeStylesModel:esm]; + [contextWindow loadConfiguration:configFile]; app = [self retain]; } @@ -191,7 +192,7 @@ Application* app = nil; [tools release]; [activeTool release]; [toolBox release]; - [propertiesWindow release]; + [contextWindow release]; [super dealloc]; } @@ -270,8 +271,8 @@ Application* app = nil; #endif } -- (void) showPropertyEditor { - [propertiesWindow present]; +- (void) showContextWindow { + [contextWindow present]; } - (void) showPreviewForDocument:(TikzDocument*)doc { @@ -319,7 +320,7 @@ Application* app = nil; } [toolBox saveConfiguration:configFile]; - [propertiesWindow saveConfiguration:configFile]; + [contextWindow saveConfiguration:configFile]; if (lastOpenFolder != nil) { [configFile setStringEntry:@"lastOpenFolder" inGroup:@"Paths" value:lastOpenFolder]; @@ -361,7 +362,7 @@ Application* app = nil; } - (void) windowDocumentChanged:(NSNotification*)n { - [propertiesWindow setDocument:[[n userInfo] objectForKey:@"document"]]; + [contextWindow setDocument:[[n userInfo] objectForKey:@"document"]]; } @end @@ -371,7 +372,7 @@ Application* app = nil; name:@"DocumentChanged" object:nil]; - [propertiesWindow setDocument:[window document]]; + [contextWindow setDocument:[window document]]; [[NSNotificationCenter defaultCenter] addObserver:self diff --git a/tikzit/src/gtk/ContextWindow.h b/tikzit/src/gtk/ContextWindow.h new file mode 100644 index 0000000..7662fe4 --- /dev/null +++ b/tikzit/src/gtk/ContextWindow.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2012 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "TZFoundation.h" +#import + +@class Configuration; +@class EdgeStylesModel; +@class NodeStylesModel; +@class PropertiesPane; +@class StyleManager; +@class TikzDocument; + +@interface ContextWindow: NSObject { + GtkWidget *window; + GtkWidget *layout; + PropertiesPane *propsPane; +} + +@property (retain) TikzDocument *document; +@property (assign) BOOL visible; + +- (id) initWithStyleManager:(StyleManager*)mgr; +- (id) initWithNodeStylesModel:(NodeStylesModel*)nsm + andEdgeStylesModel:(EdgeStylesModel*)esm; + +- (void) present; + +- (void) loadConfiguration:(Configuration*)config; +- (void) saveConfiguration:(Configuration*)config; + +@end + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/gtk/ContextWindow.m b/tikzit/src/gtk/ContextWindow.m new file mode 100644 index 0000000..c414bfc --- /dev/null +++ b/tikzit/src/gtk/ContextWindow.m @@ -0,0 +1,151 @@ +/* + * Copyright 2011-2012 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "ContextWindow.h" + +#import "Configuration.h" +#import "EdgeStylesModel.h" +#import "NodeStylesModel.h" +#import "PropertiesPane.h" +#import "StyleManager.h" + +#import "gtkhelpers.h" + +static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event, ContextWindow *window); + +@implementation ContextWindow + +- (id) init { + [self release]; + return nil; +} + +- (id) initWithStyleManager:(StyleManager*)sm { + return [self initWithNodeStylesModel:[NodeStylesModel modelWithStyleManager:sm] + andEdgeStylesModel:[EdgeStylesModel modelWithStyleManager:sm]]; +} + +- (id) initWithNodeStylesModel:(NodeStylesModel*)nsm + andEdgeStylesModel:(EdgeStylesModel*)esm { + self = [super init]; + + if (self) { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_object_ref_sink (window); + gtk_window_set_title (GTK_WINDOW (window), "Context"); + gtk_window_set_role (GTK_WINDOW (window), "context"); + gtk_window_set_type_hint (GTK_WINDOW (window), + GDK_WINDOW_TYPE_HINT_UTILITY); + gtk_window_set_default_size (GTK_WINDOW (window), 200, 500); + g_signal_connect (G_OBJECT (window), + "delete-event", + G_CALLBACK (props_window_delete_event_cb), + self); + + layout = gtk_vbox_new (FALSE, 3); + g_object_ref_sink (layout); + gtk_widget_show (layout); + gtk_container_set_border_width (GTK_CONTAINER (layout), 6); + + gtk_container_add (GTK_CONTAINER (window), layout); + + propsPane = [[PropertiesPane alloc] initWithNodeStylesModel:nsm + andEdgeStylesModel:esm]; + gtk_box_pack_start (GTK_BOX (layout), [propsPane gtkWidget], + TRUE, TRUE, 0); + + // hack to position the context window somewhere sensible + // (upper right) + gtk_window_parse_geometry (GTK_WINDOW (window), "-0+0"); + } + + return self; +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + g_object_unref (layout); + g_object_unref (window); + + [propsPane release]; + + [super dealloc]; +} + +- (TikzDocument*) document { + return [propsPane document]; +} + +- (void) setDocument:(TikzDocument*)doc { + [propsPane setDocument:doc]; +} + +- (BOOL) visible { + return gtk_widget_get_visible (window); +} + +- (void) setVisible:(BOOL)visible { + gtk_widget_set_visible (window, visible); +} + +- (void) present { + gtk_window_present (GTK_WINDOW (window)); +} + +- (void) loadConfiguration:(Configuration*)config { + [propsPane loadConfiguration:config]; + + if ([config hasGroup:@"ContextWindow"]) { + tz_restore_window (GTK_WINDOW (window), + [config integerEntry:@"x" inGroup:@"ContextWindow"], + [config integerEntry:@"y" inGroup:@"ContextWindow"], + [config integerEntry:@"w" inGroup:@"ContextWindow"], + [config integerEntry:@"h" inGroup:@"ContextWindow"]); + } + [self setVisible:[config booleanEntry:@"visible" + inGroup:@"ContextWindow" + withDefault:YES]]; +} + +- (void) saveConfiguration:(Configuration*)config { + gint x, y, w, h; + + gtk_window_get_position (GTK_WINDOW (window), &x, &y); + gtk_window_get_size (GTK_WINDOW (window), &w, &h); + + [config setIntegerEntry:@"x" inGroup:@"ContextWindow" value:x]; + [config setIntegerEntry:@"y" inGroup:@"ContextWindow" value:y]; + [config setIntegerEntry:@"w" inGroup:@"ContextWindow" value:w]; + [config setIntegerEntry:@"h" inGroup:@"ContextWindow" value:h]; + [config setBooleanEntry:@"visible" + inGroup:@"ContextWindow" + value:[self visible]]; + + [propsPane saveConfiguration:config]; +} + +@end + +static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event, ContextWindow *window) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [window setVisible:NO]; + [pool drain]; + return TRUE; +} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/gtk/Menu.m b/tikzit/src/gtk/Menu.m index e6b87fe..a741520 100644 --- a/tikzit/src/gtk/Menu.m +++ b/tikzit/src/gtk/Menu.m @@ -67,9 +67,9 @@ static void show_preamble_cb (GtkAction *action, Application *appl) { } #endif -static void show_properties_cb (GtkAction *action, Application *appl) { +static void show_context_window_cb (GtkAction *action, Application *appl) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [appl showPropertyEditor]; + [appl showContextWindow]; [pool drain]; } @@ -160,8 +160,8 @@ static GtkActionEntry app_action_entries[] = { N_("Edit the preambles used to generate the preview"), G_CALLBACK (show_preamble_cb) }, #endif - { "ShowProperties", NULL, N_("_Properties Window"), NULL, - N_("Show the property editor window"), G_CALLBACK (show_properties_cb) }, + { "ShowContextWindow", NULL, N_("_Context Window"), NULL, + N_("Show the contextual tools window"), G_CALLBACK (show_context_window_cb) }, /* HelpMenu */ { "HelpManual", GTK_STOCK_HELP, N_("_Online manual"), "F1", @@ -509,7 +509,7 @@ static const gchar ui_info[] = #endif " " " " -" " +" " #ifdef HAVE_POPPLER " " " " diff --git a/tikzit/src/gtk/PropertiesPane.h b/tikzit/src/gtk/PropertiesPane.h new file mode 100644 index 0000000..696fd0b --- /dev/null +++ b/tikzit/src/gtk/PropertiesPane.h @@ -0,0 +1,73 @@ +/* + * Copyright 2011-2012 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "TZFoundation.h" +#import + +@class Configuration; +@class EdgeNodePropertyDelegate; +@class EdgePropertyDelegate; +@class EdgeStylesModel; +@class GraphPropertyDelegate; +@class NodePropertyDelegate; +@class NodeStylesModel; +@class PropertyListEditor; +@class StyleManager; +@class TikzDocument; + +@interface PropertiesPane: NSObject { + TikzDocument *document; + BOOL blockUpdates; + + PropertyListEditor *graphProps; + PropertyListEditor *nodeProps; + PropertyListEditor *edgeProps; + PropertyListEditor *edgeNodeProps; + + GraphPropertyDelegate *graphPropDelegate; + NodePropertyDelegate *nodePropDelegate; + EdgePropertyDelegate *edgePropDelegate; + EdgeNodePropertyDelegate *edgeNodePropDelegate; + + GtkWidget *layout; + + GtkWidget *currentPropsWidget; // no ref! + + GtkWidget *graphPropsWidget; + GtkWidget *nodePropsWidget; + GtkWidget *edgePropsWidget; + + GtkEntry *nodeLabelEntry; + GtkToggleButton *edgeNodeToggle; + GtkWidget *edgeNodePropsWidget; + GtkEntry *edgeNodeLabelEntry; +} + +@property (retain) TikzDocument *document; +@property (assign) BOOL visible; +@property (readonly) GtkWidget *gtkWidget; + +- (id) initWithStyleManager:(StyleManager*)mgr; +- (id) initWithNodeStylesModel:(NodeStylesModel*)nsm + andEdgeStylesModel:(EdgeStylesModel*)esm; + +- (void) loadConfiguration:(Configuration*)config; +- (void) saveConfiguration:(Configuration*)config; + +@end + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/gtk/PropertiesPane.m b/tikzit/src/gtk/PropertiesPane.m new file mode 100644 index 0000000..684668e --- /dev/null +++ b/tikzit/src/gtk/PropertiesPane.m @@ -0,0 +1,638 @@ +/* + * Copyright 2011-2012 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "PropertiesPane.h" + +#import "Configuration.h" +#import "EdgeStylesModel.h" +#import "GraphElementProperty.h" +#import "NodeStylesModel.h" +#import "PropertyListEditor.h" +#import "StyleManager.h" +#import "TikzDocument.h" + +#import "gtkhelpers.h" + +// {{{ Internal interfaces +// {{{ GTK+ helpers +static GtkWidget *createLabelledEntry (const gchar *labelText, GtkEntry **entry); +static GtkWidget *createPropsPaneWithLabelEntry (PropertyListEditor *props, GtkEntry **labelEntry); +static GtkWidget *createBoldLabel (const gchar *text); +// }}} +// {{{ GTK+ callbacks +static void node_label_changed_cb (GtkEditable *widget, PropertiesPane *pane); +static void edge_node_label_changed_cb (GtkEditable *widget, PropertiesPane *pane); +static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane); +// }}} + +@interface PropertiesPane (Notifications) +- (void) nodeSelectionChanged:(NSNotification*)n; +- (void) edgeSelectionChanged:(NSNotification*)n; +- (void) graphChanged:(NSNotification*)n; +- (void) nodeLabelEdited:(NSString*)newValue; +- (void) edgeNodeLabelEdited:(NSString*)newValue; +- (void) edgeNodeToggled:(BOOL)newValue; +@end + +@interface PropertiesPane (Private) +- (void) _updatePane; +- (void) _setDisplayedWidget:(GtkWidget*)widget; +@end + +// {{{ Delegates + +@interface GraphPropertyDelegate : NSObject { + TikzDocument *doc; +} +- (void) setDocument:(TikzDocument*)d; +@end + +@interface NodePropertyDelegate : NSObject { + TikzDocument *doc; + Node *node; +} +- (void) setDocument:(TikzDocument*)d; +- (void) setNode:(Node*)n; +@end + +@interface EdgePropertyDelegate : NSObject { + TikzDocument *doc; + Edge *edge; +} +- (void) setDocument:(TikzDocument*)d; +- (void) setEdge:(Edge*)e; +@end + +// }}} + +// }}} +// {{{ API + +@implementation PropertiesPane + +- (id) init { + [self release]; + return nil; +} + +- (id) initWithStyleManager:(StyleManager*)sm { + return [self initWithNodeStylesModel:[NodeStylesModel modelWithStyleManager:sm] + andEdgeStylesModel:[EdgeStylesModel modelWithStyleManager:sm]]; +} + +- (id) initWithNodeStylesModel:(NodeStylesModel*)nsm + andEdgeStylesModel:(EdgeStylesModel*)esm { + self = [super init]; + + if (self) { + document = nil; + blockUpdates = NO; + + graphProps = [[PropertyListEditor alloc] init]; + graphPropDelegate = [[GraphPropertyDelegate alloc] init]; + [graphProps setDelegate:graphPropDelegate]; + + nodeProps = [[PropertyListEditor alloc] init]; + nodePropDelegate = [[NodePropertyDelegate alloc] init]; + [nodeProps setDelegate:nodePropDelegate]; + + edgeProps = [[PropertyListEditor alloc] init]; + edgePropDelegate = [[EdgePropertyDelegate alloc] init]; + [edgeProps setDelegate:edgePropDelegate]; + + edgeNodeProps = [[PropertyListEditor alloc] init]; + [edgeNodeProps setDelegate:edgePropDelegate]; + + layout = gtk_vbox_new (FALSE, 0); + g_object_ref_sink (layout); + gtk_widget_show (layout); + + /* + * Graph properties + */ + graphPropsWidget = gtk_vbox_new (FALSE, 6); + g_object_ref_sink (graphPropsWidget); + gtk_widget_show (graphPropsWidget); + + GtkWidget *label = createBoldLabel ("Graph properties"); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (graphPropsWidget), + label, + FALSE, FALSE, 0); + + gtk_widget_show ([graphProps widget]); + gtk_box_pack_start (GTK_BOX (graphPropsWidget), + [graphProps widget], + TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (layout), + graphPropsWidget, + TRUE, TRUE, 0); + + + /* + * Node properties + */ + nodePropsWidget = gtk_vbox_new (FALSE, 6); + g_object_ref_sink (nodePropsWidget); + gtk_box_pack_start (GTK_BOX (layout), + nodePropsWidget, + TRUE, TRUE, 0); + + label = createBoldLabel ("Node properties"); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (nodePropsWidget), + label, + FALSE, FALSE, 0); + + GtkWidget *labelWidget = createLabelledEntry ("Label", &nodeLabelEntry); + gtk_widget_show (labelWidget); + gtk_box_pack_start (GTK_BOX (nodePropsWidget), + labelWidget, + FALSE, FALSE, 0); + + gtk_widget_show ([nodeProps widget]); + gtk_box_pack_start (GTK_BOX (nodePropsWidget), + [nodeProps widget], + TRUE, TRUE, 0); + + g_signal_connect (G_OBJECT (nodeLabelEntry), + "changed", + G_CALLBACK (node_label_changed_cb), + self); + + /* + * Edge properties + */ + edgePropsWidget = gtk_vbox_new (FALSE, 6); + g_object_ref_sink (edgePropsWidget); + gtk_box_pack_start (GTK_BOX (layout), + edgePropsWidget, + TRUE, TRUE, 0); + + label = createBoldLabel ("Edge properties"); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (edgePropsWidget), + label, + FALSE, FALSE, 0); + + gtk_widget_show ([edgeProps widget]); + gtk_box_pack_start (GTK_BOX (edgePropsWidget), + [edgeProps widget], + TRUE, TRUE, 0); + + GtkWidget *split = gtk_hseparator_new (); + gtk_widget_show (split); + gtk_box_pack_start (GTK_BOX (edgePropsWidget), + split, + FALSE, FALSE, 0); + + edgeNodeToggle = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label ("Child node")); + g_object_ref_sink (edgeNodeToggle); + gtk_widget_show (GTK_WIDGET (edgeNodeToggle)); + gtk_box_pack_start (GTK_BOX (edgePropsWidget), + GTK_WIDGET (edgeNodeToggle), + FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (GTK_WIDGET (edgeNodeToggle)), + "toggled", + G_CALLBACK (edge_node_toggled_cb), + self); + + edgeNodePropsWidget = createPropsPaneWithLabelEntry(edgeNodeProps, &edgeNodeLabelEntry); + g_object_ref_sink (edgeNodePropsWidget); + g_object_ref_sink (edgeNodeLabelEntry); + gtk_box_pack_start (GTK_BOX (edgePropsWidget), + edgeNodePropsWidget, + TRUE, TRUE, 0); + g_signal_connect (G_OBJECT (edgeNodeLabelEntry), + "changed", + G_CALLBACK (edge_node_label_changed_cb), + self); + + /* + * Misc setup + */ + + [self _setDisplayedWidget:graphPropsWidget]; + } + + return self; +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + g_object_unref (graphPropsWidget); + g_object_unref (nodePropsWidget); + g_object_unref (edgePropsWidget); + + g_object_unref (nodeLabelEntry); + g_object_unref (edgeNodeToggle); + g_object_unref (edgeNodePropsWidget); + g_object_unref (edgeNodeLabelEntry); + + g_object_unref (layout); + + [graphProps release]; + [nodeProps release]; + [edgeProps release]; + [edgeNodeProps release]; + + [graphPropDelegate release]; + [nodePropDelegate release]; + [edgePropDelegate release]; + [edgeNodePropDelegate release]; + + [document release]; + + [super dealloc]; +} + +- (TikzDocument*) document { + return document; +} + +- (void) setDocument:(TikzDocument*)doc { + if (document != nil) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:document]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:[document pickSupport]]; + } + + [doc retain]; + [document release]; + document = doc; + + [graphPropDelegate setDocument:doc]; + [nodePropDelegate setDocument:doc]; + [edgePropDelegate setDocument:doc]; + + if (doc != nil) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(nodeSelectionChanged:) + name:@"NodeSelectionChanged" object:[doc pickSupport]]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(edgeSelectionChanged:) + name:@"EdgeSelectionChanged" object:[doc pickSupport]]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(graphChanged:) + name:@"TikzChanged" object:doc]; + } + + [self _updatePane]; +} + +- (BOOL) visible { + return gtk_widget_get_visible (layout); +} + +- (void) setVisible:(BOOL)visible { + gtk_widget_set_visible (layout, visible); +} + +- (GtkWidget*) gtkWidget { + return layout; +} + +- (void) loadConfiguration:(Configuration*)config { +} + +- (void) saveConfiguration:(Configuration*)config { +} + +@end +// }}} +// {{{ Notifications + +@implementation PropertiesPane (Notifications) + +- (void) nodeSelectionChanged:(NSNotification*)n { + [self _updatePane]; +} + +- (void) edgeSelectionChanged:(NSNotification*)n { + [self _updatePane]; +} + +- (void) graphChanged:(NSNotification*)n { + [self _updatePane]; +} + +- (void) nodeLabelEdited:(NSString*)newValue { + if (blockUpdates) + return; + + NSSet *sel = [[document pickSupport] selectedNodes]; + if ([sel count] != 1) { + NSLog(@"Expected single node selected; got %lu", [sel count]); + return; + } + + Node *node = [sel anyObject]; + [document startModifyNode:node]; + [node setLabel:newValue]; + [document endModifyNode]; +} + +- (void) edgeNodeLabelEdited:(NSString*)newValue { + if (blockUpdates) + return; + + NSSet *sel = [[document pickSupport] selectedEdges]; + if ([sel count] != 1) { + NSLog(@"Expected single edge selected; got %lu", [sel count]); + return; + } + + Edge *edge = [sel anyObject]; + if (![edge hasEdgeNode]) { + NSLog(@"Expected edge with edge node"); + return; + } + + [document startModifyEdge:edge]; + [[edge edgeNode] setLabel:newValue]; + [document endModifyEdge]; +} + +- (void) edgeNodeToggled:(BOOL)newValue { + if (blockUpdates) + return; + + NSSet *sel = [[document pickSupport] selectedEdges]; + if ([sel count] != 1) { + NSLog(@"Expected single edge selected; got %lu", [sel count]); + return; + } + + Edge *edge = [sel anyObject]; + + [document startModifyEdge:edge]; + [edge setHasEdgeNode:newValue]; + [document endModifyEdge]; +} + +@end +// }}} +// {{{ Private + +@implementation PropertiesPane (Private) + +- (void) _setDisplayedWidget:(GtkWidget*)widget { + if (currentPropsWidget != widget) { + if (currentPropsWidget) + gtk_widget_hide (currentPropsWidget); + currentPropsWidget = widget; + if (widget) + gtk_widget_show (widget); + } +} + +- (void) _updatePane { + blockUpdates = YES; + + BOOL editGraphProps = YES; + GraphElementData *data = [[document graph] data]; + [graphProps setData:data]; + + NSSet *nodeSel = [[document pickSupport] selectedNodes]; + if ([nodeSel count] == 1) { + Node *n = [nodeSel anyObject]; + [nodePropDelegate setNode:n]; + [nodeProps setData:[n data]]; + gtk_entry_set_text (nodeLabelEntry, [[n label] UTF8String]); + [self _setDisplayedWidget:nodePropsWidget]; + editGraphProps = NO; + } else { + [nodePropDelegate setNode:nil]; + [nodeProps setData:nil]; + gtk_entry_set_text (nodeLabelEntry, ""); + + NSSet *edgeSel = [[document pickSupport] selectedEdges]; + if ([edgeSel count] == 1) { + Edge *e = [edgeSel anyObject]; + [edgePropDelegate setEdge:e]; + [edgeProps setData:[e data]]; + if ([e hasEdgeNode]) { + gtk_toggle_button_set_active (edgeNodeToggle, TRUE); + gtk_widget_show (edgeNodePropsWidget); + gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), [[[e edgeNode] label] UTF8String]); + [edgeNodeProps setData:[[e edgeNode] data]]; + gtk_widget_set_sensitive (edgeNodePropsWidget, TRUE); + } else { + gtk_toggle_button_set_active (edgeNodeToggle, FALSE); + gtk_widget_hide (edgeNodePropsWidget); + gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), ""); + [edgeNodeProps setData:nil]; + gtk_widget_set_sensitive (edgeNodePropsWidget, FALSE); + } + [self _setDisplayedWidget:edgePropsWidget]; + editGraphProps = NO; + } else { + [edgePropDelegate setEdge:nil]; + [edgeProps setData:nil]; + [edgeNodeProps setData:nil]; + gtk_entry_set_text (edgeNodeLabelEntry, ""); + } + } + + if (editGraphProps) { + [self _setDisplayedWidget:graphPropsWidget]; + } + + blockUpdates = NO; +} + +@end + +// }}} +// {{{ Delegates + +@implementation GraphPropertyDelegate +- (id) init { + self = [super init]; + if (self) { + doc = nil; + } + return self; +} +- (void) setDocument:(TikzDocument*)d { + doc = d; +} +- (BOOL)startEdit { + if ([doc graph] != nil) { + [doc startChangeGraphProperties]; + return YES; + } + return NO; +} +- (void)endEdit { + [doc endChangeGraphProperties]; +} +- (void)cancelEdit { + [doc cancelChangeGraphProperties]; +} +@end + +@implementation NodePropertyDelegate +- (id) init { + self = [super init]; + if (self) { + doc = nil; + node = nil; + } + return self; +} +- (void) setDocument:(TikzDocument*)d { + doc = d; + node = nil; +} +- (void) setNode:(Node*)n { + node = n; +} +- (BOOL)startEdit { + if (node != nil) { + [doc startModifyNode:node]; + return YES; + } + return NO; +} +- (void)endEdit { + [doc endModifyNode]; +} +- (void)cancelEdit { + [doc cancelModifyNode]; +} +@end + +@implementation EdgePropertyDelegate +- (id) init { + self = [super init]; + if (self) { + doc = nil; + edge = nil; + } + return self; +} +- (void) setDocument:(TikzDocument*)d { + doc = d; + edge = nil; +} +- (void) setEdge:(Edge*)e { + edge = e; +} +- (BOOL)startEdit { + if (edge != nil) { + [doc startModifyEdge:edge]; + return YES; + } + return NO; +} +- (void)endEdit { + [doc endModifyEdge]; +} +- (void)cancelEdit { + [doc cancelModifyEdge]; +} +@end + +// }}} +// {{{ GTK+ helpers + +static GtkWidget *createLabelledEntry (const gchar *labelText, GtkEntry **entry) { + GtkBox *box = GTK_BOX (gtk_hbox_new (FALSE, 0)); + GtkWidget *label = gtk_label_new (labelText); + gtk_widget_show (label); + GtkWidget *entryWidget = gtk_entry_new (); + gtk_widget_show (entryWidget); + // container widget expand fill pad + gtk_box_pack_start (box, label, FALSE, TRUE, 5); + gtk_box_pack_start (box, entryWidget, TRUE, TRUE, 0); + if (entry) + *entry = GTK_ENTRY (entryWidget); + return GTK_WIDGET (box); +} + +static GtkWidget *createPropsPaneWithLabelEntry (PropertyListEditor *props, GtkEntry **labelEntry) { + GtkBox *box = GTK_BOX (gtk_vbox_new (FALSE, 6)); + + GtkWidget *labelWidget = createLabelledEntry ("Label", labelEntry); + gtk_widget_show (labelWidget); + // box widget expand fill pad + gtk_box_pack_start (box, labelWidget, FALSE, FALSE, 0); + gtk_box_pack_start (box, [props widget], TRUE, TRUE, 0); + gtk_widget_show ([props widget]); + return GTK_WIDGET (box); +} + +static GtkWidget *createBoldLabel (const gchar *text) { + GtkWidget *label = gtk_label_new (text); + PangoAttrList *attrs = pango_attr_list_new (); + pango_attr_list_insert (attrs, + pango_attr_weight_new (PANGO_WEIGHT_SEMIBOLD)); + gtk_label_set_attributes (GTK_LABEL (label), attrs); + pango_attr_list_unref (attrs); + return label; +} + +// }}} +// {{{ GTK+ callbacks + +static void node_label_changed_cb (GtkEditable *editable, PropertiesPane *pane) { + if (!gtk_widget_is_sensitive (GTK_WIDGET (editable))) { + // clearly wasn't the user editing + return; + } + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *newValue = gtk_editable_get_string (editable, 0, -1); + [pane nodeLabelEdited:newValue]; + + [pool drain]; +} + +static void edge_node_label_changed_cb (GtkEditable *editable, PropertiesPane *pane) { + if (!gtk_widget_is_sensitive (GTK_WIDGET (editable))) { + // clearly wasn't the user editing + return; + } + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *newValue = gtk_editable_get_string (editable, 0, -1); + [pane edgeNodeLabelEdited:newValue]; + + [pool drain]; +} + +static void edge_node_toggled_cb (GtkToggleButton *toggle, PropertiesPane *pane) { + if (!gtk_widget_is_sensitive (GTK_WIDGET (toggle))) { + // clearly wasn't the user editing + return; + } + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + gboolean newValue = gtk_toggle_button_get_active (toggle); + [pane edgeNodeToggled:newValue]; + + [pool drain]; +} + +// }}} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/gtk/PropertiesWindow.h b/tikzit/src/gtk/PropertiesWindow.h deleted file mode 100644 index cc4316f..0000000 --- a/tikzit/src/gtk/PropertiesWindow.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 Alex Merry - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#import "TZFoundation.h" -#import -#import "Configuration.h" -#import "TikzDocument.h" - -@class PropertyListEditor; -@class GraphPropertyDelegate; -@class NodePropertyDelegate; -@class EdgePropertyDelegate; -@class EdgeNodePropertyDelegate; - -@interface PropertiesWindow: NSObject { - TikzDocument *document; - BOOL blockUpdates; - - PropertyListEditor *graphProps; - PropertyListEditor *nodeProps; - PropertyListEditor *edgeProps; - PropertyListEditor *edgeNodeProps; - - GraphPropertyDelegate *graphPropDelegate; - NodePropertyDelegate *nodePropDelegate; - EdgePropertyDelegate *edgePropDelegate; - EdgeNodePropertyDelegate *edgeNodePropDelegate; - - GtkWidget *window; - GtkWidget *propertiesPane; - - GtkWidget *graphPropsWidget; - GtkWidget *nodePropsWidget; - GtkWidget *edgePropsWidget; - - GtkEntry *nodeLabelEntry; - GtkToggleButton *edgeNodeToggle; - GtkWidget *edgeNodePropsWidget; - GtkEntry *edgeNodeLabelEntry; -} - -@property (retain) TikzDocument *document; -@property (assign) BOOL visible; - -- (id) init; - -- (void) present; - -- (void) loadConfiguration:(Configuration*)config; -- (void) saveConfiguration:(Configuration*)config; - -@end - -// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/gtk/PropertiesWindow.m b/tikzit/src/gtk/PropertiesWindow.m deleted file mode 100644 index 98e4f4b..0000000 --- a/tikzit/src/gtk/PropertiesWindow.m +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright 2011 Alex Merry - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#import "PropertiesWindow.h" - -#import "Configuration.h" -#import "PropertyListEditor.h" -#import "GraphElementProperty.h" - -#import "gtkhelpers.h" - -// {{{ Internal interfaces -// {{{ GTK+ helpers -static GtkWidget *createLabelledEntry (const gchar *labelText, GtkEntry **entry); -static GtkWidget *createPropsPaneWithLabelEntry (PropertyListEditor *props, GtkEntry **labelEntry); -static GtkWidget *createBoldLabel (const gchar *text); -// }}} -// {{{ GTK+ callbacks -static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event, PropertiesWindow *window); -static void node_label_changed_cb (GtkEditable *widget, PropertiesWindow *pane); -static void edge_node_label_changed_cb (GtkEditable *widget, PropertiesWindow *pane); -static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesWindow *pane); -// }}} - -@interface PropertiesWindow (Notifications) -- (void) nodeSelectionChanged:(NSNotification*)n; -- (void) edgeSelectionChanged:(NSNotification*)n; -- (void) graphChanged:(NSNotification*)n; -- (void) nodeLabelEdited:(NSString*)newValue; -- (void) edgeNodeLabelEdited:(NSString*)newValue; -- (void) edgeNodeToggled:(BOOL)newValue; -@end - -@interface PropertiesWindow (Private) -- (void) _updatePane; -- (void) _setDisplayedWidget:(GtkWidget*)widget; -@end - -// {{{ Delegates - -@interface GraphPropertyDelegate : NSObject { - TikzDocument *doc; -} -- (void) setDocument:(TikzDocument*)d; -@end - -@interface NodePropertyDelegate : NSObject { - TikzDocument *doc; - Node *node; -} -- (void) setDocument:(TikzDocument*)d; -- (void) setNode:(Node*)n; -@end - -@interface EdgePropertyDelegate : NSObject { - TikzDocument *doc; - Edge *edge; -} -- (void) setDocument:(TikzDocument*)d; -- (void) setEdge:(Edge*)e; -@end - -// }}} - -// }}} -// {{{ API - -@implementation PropertiesWindow - -- (id) init { - self = [super init]; - - if (self) { - document = nil; - blockUpdates = NO; - - graphProps = [[PropertyListEditor alloc] init]; - graphPropDelegate = [[GraphPropertyDelegate alloc] init]; - [graphProps setDelegate:graphPropDelegate]; - - nodeProps = [[PropertyListEditor alloc] init]; - nodePropDelegate = [[NodePropertyDelegate alloc] init]; - [nodeProps setDelegate:nodePropDelegate]; - - edgeProps = [[PropertyListEditor alloc] init]; - edgePropDelegate = [[EdgePropertyDelegate alloc] init]; - [edgeProps setDelegate:edgePropDelegate]; - - edgeNodeProps = [[PropertyListEditor alloc] init]; - [edgeNodeProps setDelegate:edgePropDelegate]; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - g_object_ref_sink (window); - gtk_window_set_title (GTK_WINDOW (window), "Properties"); - gtk_window_set_role (GTK_WINDOW (window), "properties"); - gtk_window_set_type_hint (GTK_WINDOW (window), - GDK_WINDOW_TYPE_HINT_UTILITY); - gtk_window_set_default_size (GTK_WINDOW (window), 200, 500); - g_signal_connect (G_OBJECT (window), - "delete-event", - G_CALLBACK (props_window_delete_event_cb), - self); - - /* - * Graph properties - */ - graphPropsWidget = gtk_vbox_new (FALSE, 6); - g_object_ref_sink (graphPropsWidget); - gtk_container_set_border_width (GTK_CONTAINER (graphPropsWidget), 6); - gtk_widget_show (graphPropsWidget); - - GtkWidget *label = createBoldLabel ("Graph properties"); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (graphPropsWidget), - label, - FALSE, FALSE, 0); - - gtk_widget_show ([graphProps widget]); - gtk_box_pack_start (GTK_BOX (graphPropsWidget), - [graphProps widget], - TRUE, TRUE, 0); - gtk_widget_show (graphPropsWidget); - - gtk_container_add (GTK_CONTAINER (window), graphPropsWidget); - - - /* - * Node properties - */ - nodePropsWidget = gtk_vbox_new (FALSE, 6); - g_object_ref_sink (nodePropsWidget); - gtk_container_set_border_width (GTK_CONTAINER (nodePropsWidget), 6); - gtk_widget_show (nodePropsWidget); - - label = createBoldLabel ("Node properties"); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (nodePropsWidget), - label, - FALSE, FALSE, 0); - - GtkWidget *labelWidget = createLabelledEntry ("Label", &nodeLabelEntry); - gtk_widget_show (labelWidget); - gtk_box_pack_start (GTK_BOX (nodePropsWidget), - labelWidget, - FALSE, FALSE, 0); - - gtk_widget_show ([nodeProps widget]); - gtk_box_pack_start (GTK_BOX (nodePropsWidget), - [nodeProps widget], - TRUE, TRUE, 0); - - g_signal_connect (G_OBJECT (nodeLabelEntry), - "changed", - G_CALLBACK (node_label_changed_cb), - self); - - /* - * Edge properties - */ - edgePropsWidget = gtk_vbox_new (FALSE, 6); - g_object_ref_sink (edgePropsWidget); - gtk_container_set_border_width (GTK_CONTAINER (edgePropsWidget), 6); - gtk_widget_show (edgePropsWidget); - - label = createBoldLabel ("Edge properties"); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (edgePropsWidget), - label, - FALSE, FALSE, 0); - - gtk_widget_show ([edgeProps widget]); - gtk_box_pack_start (GTK_BOX (edgePropsWidget), - [edgeProps widget], - TRUE, TRUE, 0); - - GtkWidget *split = gtk_hseparator_new (); - gtk_widget_show (split); - gtk_box_pack_start (GTK_BOX (edgePropsWidget), - split, - FALSE, FALSE, 0); - - edgeNodeToggle = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_label ("Child node")); - g_object_ref_sink (edgeNodeToggle); - gtk_widget_show (GTK_WIDGET (edgeNodeToggle)); - gtk_box_pack_start (GTK_BOX (edgePropsWidget), - GTK_WIDGET (edgeNodeToggle), - FALSE, FALSE, 0); - g_signal_connect (G_OBJECT (GTK_WIDGET (edgeNodeToggle)), - "toggled", - G_CALLBACK (edge_node_toggled_cb), - self); - - edgeNodePropsWidget = createPropsPaneWithLabelEntry(edgeNodeProps, &edgeNodeLabelEntry); - g_object_ref_sink (edgeNodePropsWidget); - g_object_ref_sink (edgeNodeLabelEntry); - gtk_box_pack_start (GTK_BOX (edgePropsWidget), - edgeNodePropsWidget, - TRUE, TRUE, 0); - g_signal_connect (G_OBJECT (edgeNodeLabelEntry), - "changed", - G_CALLBACK (edge_node_label_changed_cb), - self); - - // hack to position the props window somewhere sensible - // (upper right) - gtk_window_parse_geometry (GTK_WINDOW (window), "-0+0"); - } - - return self; -} - -- (void) dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [document release]; - - g_object_unref (graphPropsWidget); - g_object_unref (nodePropsWidget); - g_object_unref (edgePropsWidget); - g_object_unref (nodeLabelEntry); - g_object_unref (edgeNodeToggle); - g_object_unref (edgeNodePropsWidget); - g_object_unref (edgeNodeLabelEntry); - - [graphProps release]; - [nodeProps release]; - [edgeProps release]; - [edgeNodeProps release]; - [graphPropDelegate release]; - [nodePropDelegate release]; - [edgePropDelegate release]; - - [super dealloc]; -} - -- (TikzDocument*) document { - return document; -} - -- (void) setDocument:(TikzDocument*)doc { - if (document != nil) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:document]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:[document pickSupport]]; - } - - [doc retain]; - [document release]; - document = doc; - - [graphPropDelegate setDocument:doc]; - [nodePropDelegate setDocument:doc]; - [edgePropDelegate setDocument:doc]; - - if (doc != nil) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(nodeSelectionChanged:) - name:@"NodeSelectionChanged" object:[doc pickSupport]]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(edgeSelectionChanged:) - name:@"EdgeSelectionChanged" object:[doc pickSupport]]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(graphChanged:) - name:@"TikzChanged" object:doc]; - } - - [self _updatePane]; -} - -- (BOOL) visible { - return gtk_widget_get_visible (window); -} - -- (void) setVisible:(BOOL)visible { - gtk_widget_set_visible (window, visible); -} - -- (void) present { - gtk_window_present (GTK_WINDOW (window)); -} - -- (void) loadConfiguration:(Configuration*)config { - if ([config hasGroup:@"PropertiesWindow"]) { - tz_restore_window (GTK_WINDOW (window), - [config integerEntry:@"x" inGroup:@"PropertiesWindow"], - [config integerEntry:@"y" inGroup:@"PropertiesWindow"], - [config integerEntry:@"w" inGroup:@"PropertiesWindow"], - [config integerEntry:@"h" inGroup:@"PropertiesWindow"]); - } - [self setVisible:[config booleanEntry:@"visible" - inGroup:@"PropertiesWindow" - withDefault:YES]]; -} - -- (void) saveConfiguration:(Configuration*)config { - gint x, y, w, h; - - gtk_window_get_position (GTK_WINDOW (window), &x, &y); - gtk_window_get_size (GTK_WINDOW (window), &w, &h); - - [config setIntegerEntry:@"x" inGroup:@"PropertiesWindow" value:x]; - [config setIntegerEntry:@"y" inGroup:@"PropertiesWindow" value:y]; - [config setIntegerEntry:@"w" inGroup:@"PropertiesWindow" value:w]; - [config setIntegerEntry:@"h" inGroup:@"PropertiesWindow" value:h]; - [config setBooleanEntry:@"visible" - inGroup:@"PropertiesWindow" - value:[self visible]]; -} - -@end -// }}} -// {{{ Notifications - -@implementation PropertiesWindow (Notifications) - -- (void) nodeSelectionChanged:(NSNotification*)n { - [self _updatePane]; -} - -- (void) edgeSelectionChanged:(NSNotification*)n { - [self _updatePane]; -} - -- (void) graphChanged:(NSNotification*)n { - [self _updatePane]; -} - -- (void) nodeLabelEdited:(NSString*)newValue { - if (blockUpdates) - return; - - NSSet *sel = [[document pickSupport] selectedNodes]; - if ([sel count] != 1) { - NSLog(@"Expected single node selected; got %lu", [sel count]); - return; - } - - Node *node = [sel anyObject]; - [document startModifyNode:node]; - [node setLabel:newValue]; - [document endModifyNode]; -} - -- (void) edgeNodeLabelEdited:(NSString*)newValue { - if (blockUpdates) - return; - - NSSet *sel = [[document pickSupport] selectedEdges]; - if ([sel count] != 1) { - NSLog(@"Expected single edge selected; got %lu", [sel count]); - return; - } - - Edge *edge = [sel anyObject]; - if (![edge hasEdgeNode]) { - NSLog(@"Expected edge with edge node"); - return; - } - - [document startModifyEdge:edge]; - [[edge edgeNode] setLabel:newValue]; - [document endModifyEdge]; -} - -- (void) edgeNodeToggled:(BOOL)newValue { - if (blockUpdates) - return; - - NSSet *sel = [[document pickSupport] selectedEdges]; - if ([sel count] != 1) { - NSLog(@"Expected single edge selected; got %lu", [sel count]); - return; - } - - Edge *edge = [sel anyObject]; - - [document startModifyEdge:edge]; - [edge setHasEdgeNode:newValue]; - [document endModifyEdge]; -} - -@end -// }}} -// {{{ Private - -@implementation PropertiesWindow (Private) - -- (void) _setDisplayedWidget:(GtkWidget*)widget { - GtkWidget *current = gtk_bin_get_child (GTK_BIN (window)); - if (current != widget) { - gtk_container_remove (GTK_CONTAINER (window), current); - gtk_container_add (GTK_CONTAINER (window), widget); - } -} - -- (void) _updatePane { - blockUpdates = YES; - - BOOL editGraphProps = YES; - GraphElementData *data = [[document graph] data]; - [graphProps setData:data]; - - NSSet *nodeSel = [[document pickSupport] selectedNodes]; - if ([nodeSel count] == 1) { - Node *n = [nodeSel anyObject]; - [nodePropDelegate setNode:n]; - [nodeProps setData:[n data]]; - gtk_entry_set_text (nodeLabelEntry, [[n label] UTF8String]); - [self _setDisplayedWidget:nodePropsWidget]; - editGraphProps = NO; - } else { - [nodePropDelegate setNode:nil]; - [nodeProps setData:nil]; - gtk_entry_set_text (nodeLabelEntry, ""); - - NSSet *edgeSel = [[document pickSupport] selectedEdges]; - if ([edgeSel count] == 1) { - Edge *e = [edgeSel anyObject]; - [edgePropDelegate setEdge:e]; - [edgeProps setData:[e data]]; - if ([e hasEdgeNode]) { - gtk_toggle_button_set_active (edgeNodeToggle, TRUE); - gtk_widget_show (edgeNodePropsWidget); - gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), [[[e edgeNode] label] UTF8String]); - [edgeNodeProps setData:[[e edgeNode] data]]; - gtk_widget_set_sensitive (edgeNodePropsWidget, TRUE); - } else { - gtk_toggle_button_set_active (edgeNodeToggle, FALSE); - gtk_widget_hide (edgeNodePropsWidget); - gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), ""); - [edgeNodeProps setData:nil]; - gtk_widget_set_sensitive (edgeNodePropsWidget, FALSE); - } - [self _setDisplayedWidget:edgePropsWidget]; - editGraphProps = NO; - } else { - [edgePropDelegate setEdge:nil]; - [edgeProps setData:nil]; - [edgeNodeProps setData:nil]; - gtk_entry_set_text (edgeNodeLabelEntry, ""); - } - } - - if (editGraphProps) { - [self _setDisplayedWidget:graphPropsWidget]; - } - - blockUpdates = NO; -} - -@end - -// }}} -// {{{ Delegates - -@implementation GraphPropertyDelegate -- (id) init { - self = [super init]; - if (self) { - doc = nil; - } - return self; -} -- (void) setDocument:(TikzDocument*)d { - doc = d; -} -- (BOOL)startEdit { - if ([doc graph] != nil) { - [doc startChangeGraphProperties]; - return YES; - } - return NO; -} -- (void)endEdit { - [doc endChangeGraphProperties]; -} -- (void)cancelEdit { - [doc cancelChangeGraphProperties]; -} -@end - -@implementation NodePropertyDelegate -- (id) init { - self = [super init]; - if (self) { - doc = nil; - node = nil; - } - return self; -} -- (void) setDocument:(TikzDocument*)d { - doc = d; - node = nil; -} -- (void) setNode:(Node*)n { - node = n; -} -- (BOOL)startEdit { - if (node != nil) { - [doc startModifyNode:node]; - return YES; - } - return NO; -} -- (void)endEdit { - [doc endModifyNode]; -} -- (void)cancelEdit { - [doc cancelModifyNode]; -} -@end - -@implementation EdgePropertyDelegate -- (id) init { - self = [super init]; - if (self) { - doc = nil; - edge = nil; - } - return self; -} -- (void) setDocument:(TikzDocument*)d { - doc = d; - edge = nil; -} -- (void) setEdge:(Edge*)e { - edge = e; -} -- (BOOL)startEdit { - if (edge != nil) { - [doc startModifyEdge:edge]; - return YES; - } - return NO; -} -- (void)endEdit { - [doc endModifyEdge]; -} -- (void)cancelEdit { - [doc cancelModifyEdge]; -} -@end - -// }}} -// {{{ GTK+ helpers - -static GtkWidget *createLabelledEntry (const gchar *labelText, GtkEntry **entry) { - GtkBox *box = GTK_BOX (gtk_hbox_new (FALSE, 0)); - GtkWidget *label = gtk_label_new (labelText); - gtk_widget_show (label); - GtkWidget *entryWidget = gtk_entry_new (); - gtk_widget_show (entryWidget); - // container widget expand fill pad - gtk_box_pack_start (box, label, FALSE, TRUE, 5); - gtk_box_pack_start (box, entryWidget, TRUE, TRUE, 0); - if (entry) - *entry = GTK_ENTRY (entryWidget); - return GTK_WIDGET (box); -} - -static GtkWidget *createPropsPaneWithLabelEntry (PropertyListEditor *props, GtkEntry **labelEntry) { - GtkBox *box = GTK_BOX (gtk_vbox_new (FALSE, 0)); - gtk_box_set_spacing (box, 6); - - GtkWidget *labelWidget = createLabelledEntry ("Label", labelEntry); - gtk_widget_show (labelWidget); - // box widget expand fill pad - gtk_box_pack_start (box, labelWidget, FALSE, FALSE, 0); - gtk_box_pack_start (box, [props widget], TRUE, TRUE, 0); - gtk_widget_show ([props widget]); - return GTK_WIDGET (box); -} - -static GtkWidget *createBoldLabel (const gchar *text) { - GtkWidget *label = gtk_label_new (text); - PangoAttrList *attrs = pango_attr_list_new (); - pango_attr_list_insert (attrs, - pango_attr_weight_new (PANGO_WEIGHT_SEMIBOLD)); - gtk_label_set_attributes (GTK_LABEL (label), attrs); - pango_attr_list_unref (attrs); - return label; -} - -// }}} -// {{{ GTK+ callbacks - -static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event, PropertiesWindow *window) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [window setVisible:NO]; - [pool drain]; - return TRUE; -} - -static void node_label_changed_cb (GtkEditable *editable, PropertiesWindow *pane) { - if (!gtk_widget_is_sensitive (GTK_WIDGET (editable))) { - // clearly wasn't the user editing - return; - } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *newValue = gtk_editable_get_string (editable, 0, -1); - [pane nodeLabelEdited:newValue]; - - [pool drain]; -} - -static void edge_node_label_changed_cb (GtkEditable *editable, PropertiesWindow *pane) { - if (!gtk_widget_is_sensitive (GTK_WIDGET (editable))) { - // clearly wasn't the user editing - return; - } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *newValue = gtk_editable_get_string (editable, 0, -1); - [pane edgeNodeLabelEdited:newValue]; - - [pool drain]; -} - -static void edge_node_toggled_cb (GtkToggleButton *toggle, PropertiesWindow *pane) { - if (!gtk_widget_is_sensitive (GTK_WIDGET (toggle))) { - // clearly wasn't the user editing - return; - } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - gboolean newValue = gtk_toggle_button_get_active (toggle); - [pane edgeNodeToggled:newValue]; - - [pool drain]; -} - -// }}} - -// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker -- cgit v1.2.3