summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Merry <alex.merry@cs.ox.ac.uk>2012-12-17 19:09:06 +0000
committerAlex Merry <alex.merry@cs.ox.ac.uk>2012-12-17 19:09:06 +0000
commit58ceedc38ed430535508360adde7b5b6d76b08e6 (patch)
treee43e8fc2e63f00ff7945bb1bd6d1c3e41b3f5e1d
parent5ac1d383d2a89d22fbf54d688d64bf6a1036df6b (diff)
Allow node and edge styles to be applied to selection
Brings back some old functionality, but in a more compact way.
-rw-r--r--tikzit/src/Makefile.am1
-rw-r--r--tikzit/src/gtk/ContextWindow.h5
-rw-r--r--tikzit/src/gtk/ContextWindow.m14
-rw-r--r--tikzit/src/gtk/EdgeStylesModel.h2
-rw-r--r--tikzit/src/gtk/EdgeStylesModel.m21
-rw-r--r--tikzit/src/gtk/NodeStylesModel.h2
-rw-r--r--tikzit/src/gtk/NodeStylesModel.m21
-rw-r--r--tikzit/src/gtk/PropertiesPane.m24
-rw-r--r--tikzit/src/gtk/SelectionPane.h56
-rw-r--r--tikzit/src/gtk/SelectionPane.m432
-rw-r--r--tikzit/src/gtk/gtkhelpers.h2
-rw-r--r--tikzit/src/gtk/gtkhelpers.m8
12 files changed, 571 insertions, 17 deletions
diff --git a/tikzit/src/Makefile.am b/tikzit/src/Makefile.am
index 6890928..b0e9e59 100644
--- a/tikzit/src/Makefile.am
+++ b/tikzit/src/Makefile.am
@@ -59,6 +59,7 @@ tikzit_SOURCES = gtk/Application.m \
gtk/PropertyListEditor.m \
gtk/RecentManager.m \
gtk/SelectTool.m \
+ gtk/SelectionPane.m \
gtk/Shape+Render.m \
gtk/StyleManager+Storage.m \
gtk/TikzDocument.m \
diff --git a/tikzit/src/gtk/ContextWindow.h b/tikzit/src/gtk/ContextWindow.h
index 7662fe4..1c2ca85 100644
--- a/tikzit/src/gtk/ContextWindow.h
+++ b/tikzit/src/gtk/ContextWindow.h
@@ -22,13 +22,16 @@
@class EdgeStylesModel;
@class NodeStylesModel;
@class PropertiesPane;
+@class SelectionPane;
@class StyleManager;
@class TikzDocument;
@interface ContextWindow: NSObject {
+ PropertiesPane *propsPane;
+ SelectionPane *selPane;
+
GtkWidget *window;
GtkWidget *layout;
- PropertiesPane *propsPane;
}
@property (retain) TikzDocument *document;
diff --git a/tikzit/src/gtk/ContextWindow.m b/tikzit/src/gtk/ContextWindow.m
index c414bfc..6fbcc59 100644
--- a/tikzit/src/gtk/ContextWindow.m
+++ b/tikzit/src/gtk/ContextWindow.m
@@ -21,6 +21,7 @@
#import "EdgeStylesModel.h"
#import "NodeStylesModel.h"
#import "PropertiesPane.h"
+#import "SelectionPane.h"
#import "StyleManager.h"
#import "gtkhelpers.h"
@@ -68,6 +69,16 @@ static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event
gtk_box_pack_start (GTK_BOX (layout), [propsPane gtkWidget],
TRUE, TRUE, 0);
+ GtkWidget *sep = gtk_hseparator_new ();
+ gtk_widget_show (sep);
+ gtk_box_pack_start (GTK_BOX (layout), sep,
+ FALSE, FALSE, 0);
+
+ selPane = [[SelectionPane alloc] initWithNodeStylesModel:nsm
+ andEdgeStylesModel:esm];
+ gtk_box_pack_start (GTK_BOX (layout), [selPane gtkWidget],
+ FALSE, FALSE, 0);
+
// hack to position the context window somewhere sensible
// (upper right)
gtk_window_parse_geometry (GTK_WINDOW (window), "-0+0");
@@ -93,6 +104,7 @@ static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event
- (void) setDocument:(TikzDocument*)doc {
[propsPane setDocument:doc];
+ [selPane setDocument:doc];
}
- (BOOL) visible {
@@ -109,6 +121,7 @@ static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event
- (void) loadConfiguration:(Configuration*)config {
[propsPane loadConfiguration:config];
+ [selPane loadConfiguration:config];
if ([config hasGroup:@"ContextWindow"]) {
tz_restore_window (GTK_WINDOW (window),
@@ -137,6 +150,7 @@ static gboolean props_window_delete_event_cb (GtkWidget *widget, GdkEvent *event
value:[self visible]];
[propsPane saveConfiguration:config];
+ [selPane saveConfiguration:config];
}
@end
diff --git a/tikzit/src/gtk/EdgeStylesModel.h b/tikzit/src/gtk/EdgeStylesModel.h
index b22ba8b..1166f92 100644
--- a/tikzit/src/gtk/EdgeStylesModel.h
+++ b/tikzit/src/gtk/EdgeStylesModel.h
@@ -54,6 +54,8 @@ enum {
- (EdgeStyle*) styleFromPath:(GtkTreePath*)path;
- (GtkTreePath*) pathFromStyle:(EdgeStyle*)style;
+- (EdgeStyle*) styleFromIter:(GtkTreeIter*)iter;
+- (GtkTreeIter*) iterFromStyle:(EdgeStyle*)style;
@end
diff --git a/tikzit/src/gtk/EdgeStylesModel.m b/tikzit/src/gtk/EdgeStylesModel.m
index 835aa35..2de57ed 100644
--- a/tikzit/src/gtk/EdgeStylesModel.m
+++ b/tikzit/src/gtk/EdgeStylesModel.m
@@ -148,6 +148,27 @@
}
return NULL;
}
+
+- (EdgeStyle*) styleFromIter:(GtkTreeIter*)iter {
+ EdgeStyle *style = nil;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), iter, EDGE_STYLES_PTR_COL, &style, -1);
+ return style;
+}
+
+- (GtkTreeIter*) iterFromStyle:(EdgeStyle*)style {
+ GtkTreeModel *m = GTK_TREE_MODEL (store);
+ GtkTreeIter row;
+ if (gtk_tree_model_get_iter_first (m, &row)) {
+ do {
+ EdgeStyle *rowStyle;
+ gtk_tree_model_get (m, &row, EDGE_STYLES_PTR_COL, &rowStyle, -1);
+ if (style == rowStyle) {
+ return gtk_tree_iter_copy (&row);
+ }
+ } while (gtk_tree_model_iter_next (m, &row));
+ }
+ return NULL;
+}
@end
// }}}
diff --git a/tikzit/src/gtk/NodeStylesModel.h b/tikzit/src/gtk/NodeStylesModel.h
index 1a7bf02..a048560 100644
--- a/tikzit/src/gtk/NodeStylesModel.h
+++ b/tikzit/src/gtk/NodeStylesModel.h
@@ -54,6 +54,8 @@ enum {
- (NodeStyle*) styleFromPath:(GtkTreePath*)path;
- (GtkTreePath*) pathFromStyle:(NodeStyle*)style;
+- (NodeStyle*) styleFromIter:(GtkTreeIter*)iter;
+- (GtkTreeIter*) iterFromStyle:(NodeStyle*)style;
@end
diff --git a/tikzit/src/gtk/NodeStylesModel.m b/tikzit/src/gtk/NodeStylesModel.m
index 68242e5..3cc5771 100644
--- a/tikzit/src/gtk/NodeStylesModel.m
+++ b/tikzit/src/gtk/NodeStylesModel.m
@@ -154,6 +154,27 @@
}
return NULL;
}
+
+- (NodeStyle*) styleFromIter:(GtkTreeIter*)iter {
+ NodeStyle *style = nil;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), iter, NODE_STYLES_PTR_COL, &style, -1);
+ return style;
+}
+
+- (GtkTreeIter*) iterFromStyle:(NodeStyle*)style {
+ GtkTreeModel *m = GTK_TREE_MODEL (store);
+ GtkTreeIter row;
+ if (gtk_tree_model_get_iter_first (m, &row)) {
+ do {
+ NodeStyle *rowStyle;
+ gtk_tree_model_get (m, &row, NODE_STYLES_PTR_COL, &rowStyle, -1);
+ if (style == rowStyle) {
+ return gtk_tree_iter_copy (&row);
+ }
+ } while (gtk_tree_model_iter_next (m, &row));
+ }
+ return NULL;
+}
@end
// }}}
diff --git a/tikzit/src/gtk/PropertiesPane.m b/tikzit/src/gtk/PropertiesPane.m
index 684668e..990304e 100644
--- a/tikzit/src/gtk/PropertiesPane.m
+++ b/tikzit/src/gtk/PropertiesPane.m
@@ -17,12 +17,8 @@
#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"
@@ -84,18 +80,18 @@ static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane)
@implementation PropertiesPane
-- (id) init {
- [self release];
- return nil;
-}
-
+// we don't currently use the styles models
- (id) initWithStyleManager:(StyleManager*)sm {
- return [self initWithNodeStylesModel:[NodeStylesModel modelWithStyleManager:sm]
- andEdgeStylesModel:[EdgeStylesModel modelWithStyleManager:sm]];
+ return [self init];
}
+// we don't currently use the styles models
- (id) initWithNodeStylesModel:(NodeStylesModel*)nsm
andEdgeStylesModel:(EdgeStylesModel*)esm {
+ return [self init];
+}
+
+- (id) init {
self = [super init];
if (self) {
@@ -580,11 +576,7 @@ static GtkWidget *createPropsPaneWithLabelEntry (PropertyListEditor *props, GtkE
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);
+ label_set_bold (GTK_LABEL (label));
return label;
}
diff --git a/tikzit/src/gtk/SelectionPane.h b/tikzit/src/gtk/SelectionPane.h
new file mode 100644
index 0000000..57a766a
--- /dev/null
+++ b/tikzit/src/gtk/SelectionPane.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011-2012 Alex Merry <dev@randomguy3.me.uk>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#import "TZFoundation.h"
+#import <gtk/gtk.h>
+
+@class Configuration;
+@class EdgeStylesModel;
+@class NodeStylesModel;
+@class StyleManager;
+@class TikzDocument;
+
+@interface SelectionPane: NSObject {
+ TikzDocument *document;
+
+ NodeStylesModel *nodeStylesModel;
+ EdgeStylesModel *edgeStylesModel;
+
+ GtkWidget *layout;
+
+ GtkWidget *nodeStyleCombo;
+ GtkWidget *applyNodeStyleButton;
+ GtkWidget *clearNodeStyleButton;
+ GtkWidget *edgeStyleCombo;
+ GtkWidget *applyEdgeStyleButton;
+ GtkWidget *clearEdgeStyleButton;
+}
+
+@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/SelectionPane.m b/tikzit/src/gtk/SelectionPane.m
new file mode 100644
index 0000000..2931258
--- /dev/null
+++ b/tikzit/src/gtk/SelectionPane.m
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2011-2012 Alex Merry <dev@randomguy3.me.uk>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#import "SelectionPane.h"
+
+#import "Configuration.h"
+#import "EdgeStylesModel.h"
+#import "NodeStylesModel.h"
+#import "TikzDocument.h"
+
+#import "gtkhelpers.h"
+
+// {{{ Internal interfaces
+
+static void node_style_changed_cb (GtkComboBox *widget, SelectionPane *pane);
+static void apply_node_style_button_cb (GtkButton *widget, SelectionPane *pane);
+static void clear_node_style_button_cb (GtkButton *widget, SelectionPane *pane);
+static void edge_style_changed_cb (GtkComboBox *widget, SelectionPane *pane);
+static void apply_edge_style_button_cb (GtkButton *widget, SelectionPane *pane);
+static void clear_edge_style_button_cb (GtkButton *widget, SelectionPane *pane);
+
+static void setup_style_cell_layout (GtkCellLayout *cell_layout, gint pixbuf_col, gint name_col);
+
+@interface SelectionPane (Notifications)
+- (void) nodeSelectionChanged:(NSNotification*)n;
+- (void) edgeSelectionChanged:(NSNotification*)n;
+@end
+
+@interface SelectionPane (Private)
+- (void) _updateNodeStyleButtons;
+- (void) _updateEdgeStyleButtons;
+- (NodeStyle*) _selectedNodeStyle;
+- (EdgeStyle*) _selectedEdgeStyle;
+- (void) _applyNodeStyle;
+- (void) _clearNodeStyle;
+- (void) _applyEdgeStyle;
+- (void) _clearEdgeStyle;
+@end
+
+// }}}
+// {{{ API
+
+@implementation SelectionPane
+
+- (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) {
+ nodeStylesModel = [nsm retain];
+ edgeStylesModel = [esm retain];
+
+ layout = gtk_vbox_new (FALSE, 0);
+ g_object_ref_sink (layout);
+ gtk_widget_show (layout);
+
+ GtkWidget *label = gtk_label_new ("Selection");
+ label_set_bold (GTK_LABEL (label));
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (layout), label,
+ FALSE, FALSE, 0);
+
+ GtkWidget *lvl1_box = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (layout), lvl1_box,
+ FALSE, FALSE, 3);
+
+ nodeStyleCombo = gtk_combo_box_new_with_model ([nodeStylesModel model]);
+ g_object_ref_sink (nodeStyleCombo);
+ setup_style_cell_layout (GTK_CELL_LAYOUT (nodeStyleCombo),
+ NODE_STYLES_ICON_COL,
+ NODE_STYLES_NAME_COL);
+ g_signal_connect (G_OBJECT (nodeStyleCombo),
+ "changed",
+ G_CALLBACK (node_style_changed_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl1_box), nodeStyleCombo,
+ FALSE, FALSE, 0);
+
+ GtkWidget *lvl2_box = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (lvl1_box), lvl2_box,
+ FALSE, FALSE, 0);
+
+ applyNodeStyleButton = gtk_button_new_with_label ("Apply");
+ g_object_ref_sink (applyNodeStyleButton);
+ gtk_widget_set_tooltip_text (applyNodeStyleButton, "Apply style to selected nodes");
+ gtk_widget_set_sensitive (applyNodeStyleButton, FALSE);
+ g_signal_connect (G_OBJECT (applyNodeStyleButton),
+ "clicked",
+ G_CALLBACK (apply_node_style_button_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl2_box), applyNodeStyleButton,
+ FALSE, FALSE, 0);
+
+ clearNodeStyleButton = gtk_button_new_with_label ("Clear");
+ g_object_ref_sink (clearNodeStyleButton);
+ gtk_widget_set_tooltip_text (clearNodeStyleButton, "Clear style from selected nodes");
+ gtk_widget_set_sensitive (clearNodeStyleButton, FALSE);
+ g_signal_connect (G_OBJECT (clearNodeStyleButton),
+ "clicked",
+ G_CALLBACK (clear_node_style_button_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl2_box), clearNodeStyleButton,
+ FALSE, FALSE, 0);
+
+ lvl1_box = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (layout), lvl1_box,
+ FALSE, FALSE, 3);
+
+ edgeStyleCombo = gtk_combo_box_new_with_model ([edgeStylesModel model]);
+ g_object_ref_sink (edgeStyleCombo);
+ setup_style_cell_layout (GTK_CELL_LAYOUT (edgeStyleCombo),
+ EDGE_STYLES_ICON_COL,
+ EDGE_STYLES_NAME_COL);
+ g_signal_connect (G_OBJECT (edgeStyleCombo),
+ "changed",
+ G_CALLBACK (edge_style_changed_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl1_box), edgeStyleCombo,
+ FALSE, FALSE, 0);
+
+ lvl2_box = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (lvl1_box), lvl2_box,
+ FALSE, FALSE, 0);
+
+ applyEdgeStyleButton = gtk_button_new_with_label ("Apply");
+ g_object_ref_sink (applyEdgeStyleButton);
+ gtk_widget_set_tooltip_text (applyEdgeStyleButton, "Apply style to selected edges");
+ gtk_widget_set_sensitive (applyEdgeStyleButton, FALSE);
+ g_signal_connect (G_OBJECT (applyEdgeStyleButton),
+ "clicked",
+ G_CALLBACK (apply_edge_style_button_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl2_box), applyEdgeStyleButton,
+ FALSE, FALSE, 0);
+
+ clearEdgeStyleButton = gtk_button_new_with_label ("Clear");
+ g_object_ref_sink (clearEdgeStyleButton);
+ gtk_widget_set_tooltip_text (clearEdgeStyleButton, "Clear style from selected edges");
+ gtk_widget_set_sensitive (clearEdgeStyleButton, FALSE);
+ g_signal_connect (G_OBJECT (clearEdgeStyleButton),
+ "clicked",
+ G_CALLBACK (clear_edge_style_button_cb),
+ self);
+ gtk_box_pack_start (GTK_BOX (lvl2_box), clearEdgeStyleButton,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (layout);
+ }
+
+ return self;
+}
+
+- (void) dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ g_object_unref (nodeStyleCombo);
+ g_object_unref (applyNodeStyleButton);
+ g_object_unref (clearNodeStyleButton);
+ g_object_unref (edgeStyleCombo);
+ g_object_unref (applyEdgeStyleButton);
+ g_object_unref (clearEdgeStyleButton);
+
+ g_object_unref (layout);
+
+ [nodeStylesModel release];
+ [edgeStylesModel release];
+
+ [document release];
+
+ [super dealloc];
+}
+
+- (TikzDocument*) document {
+ return document;
+}
+
+- (void) setDocument:(TikzDocument*)doc {
+ if (document != nil) {
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:nil
+ object:[document pickSupport]];
+ }
+
+ [doc retain];
+ [document release];
+ document = 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]];
+ }
+
+ [self _updateNodeStyleButtons];
+ [self _updateEdgeStyleButtons];
+}
+
+- (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 {
+ NSString *nodeStyleName = [config stringEntry:@"SelectedNodeStyle"
+ inGroup:@"SelectionPane"
+ withDefault:nil];
+ NodeStyle *nodeStyle = [[nodeStylesModel styleManager] nodeStyleForName:nodeStyleName];
+ if (nodeStyle == nil) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (nodeStyleCombo), -1);
+ } else {
+ GtkTreeIter *iter = [nodeStylesModel iterFromStyle:nodeStyle];
+ if (iter) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (nodeStyleCombo), iter);
+ gtk_tree_iter_free (iter);
+ }
+ }
+
+ NSString *edgeStyleName = [config stringEntry:@"SelectedEdgeStyle"
+ inGroup:@"SelectionPane"
+ withDefault:nil];
+ EdgeStyle *edgeStyle = [[edgeStylesModel styleManager] edgeStyleForName:edgeStyleName];
+ if (edgeStyle == nil) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (edgeStyleCombo), -1);
+ } else {
+ GtkTreeIter *iter = [edgeStylesModel iterFromStyle:edgeStyle];
+ if (iter) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (edgeStyleCombo), iter);
+ gtk_tree_iter_free (iter);
+ }
+ }
+}
+
+- (void) saveConfiguration:(Configuration*)config {
+ [config setStringEntry:@"SelectedNodeStyle"
+ inGroup:@"SelectionPane"
+ value:[[self _selectedNodeStyle] name]];
+ [config setStringEntry:@"SelectedEdgeStyle"
+ inGroup:@"SelectionPane"
+ value:[[self _selectedEdgeStyle] name]];
+}
+
+@end
+
+// }}}
+// {{{ Notifications
+
+@implementation SelectionPane (Notifications)
+- (void) nodeSelectionChanged:(NSNotification*)n {
+ [self _updateNodeStyleButtons];
+}
+
+- (void) edgeSelectionChanged:(NSNotification*)n {
+ [self _updateEdgeStyleButtons];
+}
+@end
+
+// }}}
+// {{{ Private
+
+@implementation SelectionPane (Private)
+- (void) _updateNodeStyleButtons {
+ gboolean hasNodeSelection = [[[document pickSupport] selectedNodes] count] > 0;
+
+ gtk_widget_set_sensitive (applyNodeStyleButton,
+ hasNodeSelection && [self _selectedNodeStyle] != nil);
+ gtk_widget_set_sensitive (clearNodeStyleButton, hasNodeSelection);
+}
+
+- (void) _updateEdgeStyleButtons {
+ gboolean hasEdgeSelection = [[[document pickSupport] selectedEdges] count] > 0;
+
+ gtk_widget_set_sensitive (applyEdgeStyleButton,
+ hasEdgeSelection && [self _selectedEdgeStyle] != nil);
+ gtk_widget_set_sensitive (clearEdgeStyleButton, hasEdgeSelection);
+}
+
+- (NodeStyle*) _selectedNodeStyle {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (nodeStyleCombo), &iter)) {
+ return [nodeStylesModel styleFromIter:&iter];
+ } else {
+ return nil;
+ }
+}
+
+- (EdgeStyle*) _selectedEdgeStyle {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (edgeStyleCombo), &iter)) {
+ return [edgeStylesModel styleFromIter:&iter];
+ } else {
+ return nil;
+ }
+}
+
+- (void) _applyNodeStyle {
+ [document startModifyNodes:[[document pickSupport] selectedNodes]];
+
+ NodeStyle *style = [self _selectedNodeStyle];
+ for (Node *node in [[document pickSupport] selectedNodes]) {
+ [node setStyle:style];
+ }
+
+ [document endModifyNodes];
+}
+
+- (void) _clearNodeStyle {
+ [document startModifyNodes:[[document pickSupport] selectedNodes]];
+
+ for (Node *node in [[document pickSupport] selectedNodes]) {
+ [node setStyle:nil];
+ }
+
+ [document endModifyNodes];
+}
+
+- (void) _applyEdgeStyle {
+ [document startModifyEdges:[[document pickSupport] selectedEdges]];
+
+ EdgeStyle *style = [self _selectedEdgeStyle];
+ for (Edge *edge in [[document pickSupport] selectedEdges]) {
+ [edge setStyle:style];
+ }
+
+ [document endModifyEdges];
+}
+
+- (void) _clearEdgeStyle {
+ [document startModifyEdges:[[document pickSupport] selectedEdges]];
+
+ for (Edge *edge in [[document pickSupport] selectedEdges]) {
+ [edge setStyle:nil];
+ }
+
+ [document endModifyEdges];
+}
+@end
+
+// }}}
+// {{{ GTK+ callbacks
+
+static void node_style_changed_cb (GtkComboBox *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _updateNodeStyleButtons];
+ [pool drain];
+}
+
+static void apply_node_style_button_cb (GtkButton *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _applyNodeStyle];
+ [pool drain];
+}
+
+static void clear_node_style_button_cb (GtkButton *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _clearNodeStyle];
+ [pool drain];
+}
+
+static void edge_style_changed_cb (GtkComboBox *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _updateEdgeStyleButtons];
+ [pool drain];
+}
+
+static void apply_edge_style_button_cb (GtkButton *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _applyEdgeStyle];
+ [pool drain];
+}
+
+static void clear_edge_style_button_cb (GtkButton *widget, SelectionPane *pane) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [pane _clearEdgeStyle];
+ [pool drain];
+}
+
+// }}}
+//
+static void setup_style_cell_layout (GtkCellLayout *cell_layout, gint pixbuf_col, gint name_col) {
+ gtk_cell_layout_clear (cell_layout);
+ GtkCellRenderer *pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (cell_layout, pixbuf_renderer, FALSE);
+ gtk_cell_layout_set_attributes (
+ cell_layout,
+ pixbuf_renderer,
+ "pixbuf", pixbuf_col,
+ NULL);
+ GtkCellRenderer *text_renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (cell_layout, text_renderer, FALSE);
+ gtk_cell_layout_set_attributes (
+ cell_layout,
+ text_renderer,
+ "text", name_col,
+ NULL);
+}
+
+// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker
diff --git a/tikzit/src/gtk/gtkhelpers.h b/tikzit/src/gtk/gtkhelpers.h
index 59b69bc..a28b127 100644
--- a/tikzit/src/gtk/gtkhelpers.h
+++ b/tikzit/src/gtk/gtkhelpers.h
@@ -48,4 +48,6 @@ GdkPixbuf * pixbuf_get_from_surface(cairo_surface_t *surface);
void tz_restore_window (GtkWindow *window, gint x, gint y, gint w, gint h);
+void label_set_bold (GtkLabel *label);
+
// vim:ft=objc:sts=2:sw=2:et
diff --git a/tikzit/src/gtk/gtkhelpers.m b/tikzit/src/gtk/gtkhelpers.m
index ce02618..c37077b 100644
--- a/tikzit/src/gtk/gtkhelpers.m
+++ b/tikzit/src/gtk/gtkhelpers.m
@@ -226,4 +226,12 @@ void tz_restore_window (GtkWindow *window, gint x, gint y, gint w, gint h)
}
}
+void label_set_bold (GtkLabel *label) {
+ PangoAttrList *attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs,
+ pango_attr_weight_new (PANGO_WEIGHT_SEMIBOLD));
+ gtk_label_set_attributes (label, attrs);
+ pango_attr_list_unref (attrs);
+}
+
// vim:ft=objc:ts=8:et:sts=4:sw=4