From 87294b7ebc03156f223052ca2a6c70463df568f0 Mon Sep 17 00:00:00 2001 From: randomguy3 Date: Tue, 10 Jan 2012 15:40:11 +0000 Subject: GTK: Edge style support git-svn-id: https://tikzit.svn.sourceforge.net/svnroot/tikzit/trunk@375 7c02a99a-9b00-45e3-bf44-6f3dd7fddb64 --- tikzit/src/Makefile.am | 17 ++ tikzit/src/common/Graph.m | 19 +- tikzit/src/common/GraphChange.h | 27 +++ tikzit/src/common/GraphChange.m | 34 +++ tikzit/src/linux/Edge+Render.m | 27 ++- tikzit/src/linux/EdgeStyleEditor.h | 39 +++ tikzit/src/linux/EdgeStyleEditor.m | 322 +++++++++++++++++++++++++ tikzit/src/linux/EdgeStyleSelector.h | 69 ++++++ tikzit/src/linux/EdgeStyleSelector.m | 454 +++++++++++++++++++++++++++++++++++ tikzit/src/linux/EdgeStylesPalette.h | 46 ++++ tikzit/src/linux/EdgeStylesPalette.m | 283 ++++++++++++++++++++++ tikzit/src/linux/MainWindow.h | 14 +- tikzit/src/linux/MainWindow.m | 82 ++++--- tikzit/src/linux/NodeStyleEditor.h | 10 +- tikzit/src/linux/NodeStyleEditor.m | 414 ++++++++++++++++---------------- tikzit/src/linux/NodeStyleSelector.h | 12 +- tikzit/src/linux/NodeStyleSelector.m | 48 ++-- tikzit/src/linux/NodeStylesPalette.h | 8 +- tikzit/src/linux/NodeStylesPalette.m | 54 ++--- tikzit/src/linux/PropertyPane.h | 10 +- tikzit/src/linux/PropertyPane.m | 1 + tikzit/src/linux/StylesPane.h | 49 ++++ tikzit/src/linux/StylesPane.m | 143 +++++++++++ tikzit/src/linux/TikzDocument.h | 7 + tikzit/src/linux/TikzDocument.m | 34 +++ 25 files changed, 1873 insertions(+), 350 deletions(-) create mode 100644 tikzit/src/linux/EdgeStyleEditor.h create mode 100644 tikzit/src/linux/EdgeStyleEditor.m create mode 100644 tikzit/src/linux/EdgeStyleSelector.h create mode 100644 tikzit/src/linux/EdgeStyleSelector.m create mode 100644 tikzit/src/linux/EdgeStylesPalette.h create mode 100644 tikzit/src/linux/EdgeStylesPalette.m create mode 100644 tikzit/src/linux/StylesPane.h create mode 100644 tikzit/src/linux/StylesPane.m (limited to 'tikzit/src') diff --git a/tikzit/src/Makefile.am b/tikzit/src/Makefile.am index 15bc5d9..cbd9cfc 100644 --- a/tikzit/src/Makefile.am +++ b/tikzit/src/Makefile.am @@ -28,6 +28,9 @@ tikzit_SOURCES = linux/CairoRenderContext.m \ linux/Configuration.m \ linux/Edge+Render.m \ linux/EdgeStyle+Storage.m \ + linux/EdgeStyleEditor.m \ + linux/EdgeStyleSelector.m \ + linux/EdgeStylesPalette.m \ linux/FileChooserDialog.m \ linux/GraphInputHandler.m \ linux/GraphRenderer.m \ @@ -47,6 +50,7 @@ tikzit_SOURCES = linux/CairoRenderContext.m \ linux/RecentManager.m \ linux/Shape+Render.m \ linux/StyleManager+Storage.m \ + linux/StylesPane.m \ linux/TikzDocument.m \ linux/WidgetSurface.m \ linux/cairo_helpers.m \ @@ -129,8 +133,21 @@ linux/logodata.m: ../share/icons/hicolor/*/apps/tikzit.png logo128 ../share/icons/hicolor/128x128/apps/tikzit.png \ > $@ +linux/edgedecdata.m: ../AH_*.png ../ED_*.png + $(AM_V_GEN)gdk-pixbuf-csource --struct --static --raw --build-list \ + AH_none_pixdata ../AH_none.png \ + AH_latex_head_pixdata ../AH_latex_head.png \ + AH_latex_tail_pixdata ../AH_latex_tail.png \ + AH_plain_head_pixdata ../AH_plain_head.png \ + AH_plain_tail_pixdata ../AH_plain_tail.png \ + ED_none_pixdata ../ED_none.png \ + ED_arrow_pixdata ../ED_arrow.png \ + ED_tick_pixdata ../ED_tick.png \ + > $@ + linux/Menu.m: linux/icondata.m linux/logo.m: linux/logodata.m +linux/EdgeStyleEditor.m: linux/edgedecdata.m EXTRA_DIST = linux/*.h common/*.h $(PARSERFILES) common/tikzlexer.lm common/tikzparser.ym MAINTAINERCLEANFILES = $(PARSERFILES) linux/icondata.m linux/logodata.m diff --git a/tikzit/src/common/Graph.m b/tikzit/src/common/Graph.m index 62774f5..4250f7f 100644 --- a/tikzit/src/common/Graph.m +++ b/tikzit/src/common/Graph.m @@ -425,15 +425,26 @@ [[ch nodeRef] setPropertiesFromNode:[ch nwNode]]; break; case NodesPropertyChange: - en = [[ch nwNodeTable] keyEnumerator]; - Node *key; - while ((key = [en nextObject])) { - [key setPropertiesFromNode:[[ch nwNodeTable] objectForKey:key]]; + { + en = [[ch nwNodeTable] keyEnumerator]; + Node *key; + while ((key = [en nextObject])) { + [key setPropertiesFromNode:[[ch nwNodeTable] objectForKey:key]]; + } } break; case EdgePropertyChange: [[ch edgeRef] setPropertiesFromEdge:[ch nwEdge]]; break; + case EdgesPropertyChange: + { + en = [[ch nwEdgeTable] keyEnumerator]; + Edge *key; + while ((key = [en nextObject])) { + [key setPropertiesFromEdge:[[ch nwEdgeTable] objectForKey:key]]; + } + } + break; case NodesShift: en = [[ch affectedNodes] objectEnumerator]; NSPoint newLoc; diff --git a/tikzit/src/common/GraphChange.h b/tikzit/src/common/GraphChange.h index 0ad0c97..63bdfad 100644 --- a/tikzit/src/common/GraphChange.h +++ b/tikzit/src/common/GraphChange.h @@ -31,6 +31,7 @@ typedef enum { NodePropertyChange, EdgePropertyChange, NodesPropertyChange, + EdgesPropertyChange, NodesShift, NodesFlip, BoundingBoxChange, @@ -63,6 +64,7 @@ typedef enum { Node *oldNode, *nwNode; Edge *oldEdge, *nwEdge; BasicMapTable *oldNodeTable, *nwNodeTable; + BasicMapTable *oldEdgeTable, *nwEdgeTable; NSRect oldBoundingBox, nwBoundingBox; GraphElementData *oldGraphData, *nwGraphData; } @@ -145,6 +147,18 @@ typedef enum { */ @property (retain) BasicMapTable *nwNodeTable; +/*! + @property oldEdgeTable + @brief A a table containing copies of a set of edges pre-change. + */ +@property (retain) BasicMapTable *oldEdgeTable; + +/*! + @property nwEdgeTable + @brief A a table containing copies of a set of edges post-change. + */ +@property (retain) BasicMapTable *nwEdgeTable; + /*! @property oldBoundingBox @brief The old bounding box. @@ -227,6 +241,19 @@ typedef enum { + (GraphChange*)propertyChangeOfNodesFromOldCopies:(BasicMapTable*)oldC toNewCopies:(BasicMapTable*)newC; +/*! + @brief Construct a property change of set of edges. + @details Construct a property change of set of edges. oldC and newC should be + constructed using the class method [Graph edgeTableForEdges:] before + and after the property change, respectively. The affected edges are + keys(oldC) = keys(newC). + @param oldC a table of copies of edges pre-change + @param newC a table of copies of edges post-change + @result A property change of a set of edges. + */ ++ (GraphChange*)propertyChangeOfEdgesFromOldCopies:(BasicMapTable*)oldC + toNewCopies:(BasicMapTable*)newC; + /*! @brief Construct a shift of a set of nodes by a given point. diff --git a/tikzit/src/common/GraphChange.m b/tikzit/src/common/GraphChange.m index d09e732..3635383 100644 --- a/tikzit/src/common/GraphChange.m +++ b/tikzit/src/common/GraphChange.m @@ -142,6 +142,24 @@ } } +- (BasicMapTable*)oldEdgeTable { return oldEdgeTable; } + +- (void)setOldEdgeTable:(BasicMapTable*)tab { + if (oldEdgeTable != tab) { + [oldEdgeTable release]; + oldEdgeTable = [tab retain]; + } +} + +- (BasicMapTable*)nwEdgeTable { return nwEdgeTable; } + +- (void)setNwEdgeTable:(BasicMapTable*)tab { + if (nwEdgeTable != tab) { + [nwEdgeTable release]; + nwEdgeTable = [tab retain]; + } +} + - (NSRect)oldBoundingBox { return oldBoundingBox; } - (void)setOldBoundingBox:(NSRect)bbox { @@ -204,6 +222,11 @@ [inverse setOldEdge:[self nwEdge]]; [inverse setNwEdge:[self oldEdge]]; break; + case EdgesPropertyChange: + [inverse setChangeType:EdgesPropertyChange]; + [inverse setOldEdgeTable:[self nwEdgeTable]]; + [inverse setNwEdgeTable:[self oldEdgeTable]]; + break; case NodesShift: [inverse setChangeType:NodesShift]; [inverse setAffectedNodes:[self affectedNodes]]; @@ -240,6 +263,8 @@ [oldEdge release]; [oldNodeTable release]; [nwNodeTable release]; + [oldEdgeTable release]; + [nwEdgeTable release]; [super dealloc]; } @@ -287,6 +312,15 @@ return [gc autorelease]; } ++ (GraphChange*)propertyChangeOfEdgesFromOldCopies:(BasicMapTable*)oldC + toNewCopies:(BasicMapTable*)newC { + GraphChange *gc = [[GraphChange alloc] init]; + [gc setChangeType:EdgesPropertyChange]; + [gc setOldEdgeTable:oldC]; + [gc setNwEdgeTable:newC]; + return [gc autorelease]; +} + + (GraphChange*)shiftNodes:(NSSet*)ns byPoint:(NSPoint)p { GraphChange *gc = [[GraphChange alloc] init]; [gc setChangeType:NodesShift]; diff --git a/tikzit/src/linux/Edge+Render.m b/tikzit/src/linux/Edge+Render.m index 2e5f127..a6738b7 100644 --- a/tikzit/src/linux/Edge+Render.m +++ b/tikzit/src/linux/Edge+Render.m @@ -134,19 +134,19 @@ static const float cpLineWidth = 1.0; [context moveTo:c_source]; [context curveTo:c_target withCp1:c_cp1 andCp2:c_cp2]; - if ([self style] != nil) { + if ([self style] != nil) { // draw edge decoration switch ([[self style] decorationStyle]) { case ED_None: break; case ED_Tick: - [context moveTo:[transformer toScreen:[self leftNormal]]]; - [context lineTo:[transformer toScreen:[self rightNormal]]]; + [context moveTo:[transformer toScreen:[self leftNormal]]]; + [context lineTo:[transformer toScreen:[self rightNormal]]]; break; case ED_Arrow: - [context moveTo:[transformer toScreen:[self leftNormal]]]; - [context lineTo:[transformer toScreen:[self midTan]]]; - [context lineTo:[transformer toScreen:[self rightNormal]]]; + [context moveTo:[transformer toScreen:[self leftNormal]]]; + [context lineTo:[transformer toScreen:[self midTan]]]; + [context lineTo:[transformer toScreen:[self rightNormal]]]; break; } } @@ -157,7 +157,8 @@ static const float cpLineWidth = 1.0; [self updateControls]; [context saveState]; - [context setLineWidth:edgeWidth]; + const CGFloat lineWidth = style ? [style thickness] : edgeWidth; + [context setLineWidth:lineWidth]; [self createStrokePathInContext:context withTransformer:[surface transformer]]; RColor color = BlackRColor; if (selected) { @@ -170,11 +171,11 @@ static const float cpLineWidth = 1.0; [self renderControlsToSurface:surface withContext:context]; } - if ([self hasEdgeNode]) { - NSPoint labelPt = [[surface transformer] toScreen:[self mid]]; - [[self edgeNode] renderLabelAt:labelPt - withContext:context]; - } + if ([self hasEdgeNode]) { + NSPoint labelPt = [[surface transformer] toScreen:[self mid]]; + [[self edgeNode] renderLabelAt:labelPt + withContext:context]; + } } - (NSRect) renderedBoundsWithTransformer:(Transformer*)t whenSelected:(BOOL)selected { @@ -205,4 +206,4 @@ static const float cpLineWidth = 1.0; @end -// vim:ft=objc:ts=4:noet:sts=4:sw=4 +// vim:ft=objc:ts=4:et:sts=4:sw=4 diff --git a/tikzit/src/linux/EdgeStyleEditor.h b/tikzit/src/linux/EdgeStyleEditor.h new file mode 100644 index 0000000..70a8747 --- /dev/null +++ b/tikzit/src/linux/EdgeStyleEditor.h @@ -0,0 +1,39 @@ +/* + * Copyright 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 EdgeStyle; + +@interface EdgeStyleEditor: NSObject { + EdgeStyle *style; + GtkTable *table; + GtkEntry *nameEdit; + GtkComboBox *decorationCombo; + GtkAdjustment *thicknessAdj; + BOOL blockSignals; +} + +@property (retain) EdgeStyle *style; +@property (readonly) GtkWidget *widget; + +- (id) init; + +@end + +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/EdgeStyleEditor.m b/tikzit/src/linux/EdgeStyleEditor.m new file mode 100644 index 0000000..a0b3df2 --- /dev/null +++ b/tikzit/src/linux/EdgeStyleEditor.m @@ -0,0 +1,322 @@ +/* + * Copyright 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 "EdgeStyleEditor.h" + +#import "EdgeStyle.h" +#import "Shape.h" + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-sign" +#import "edgedecdata.m" +#pragma GCC diagnostic pop + +enum { + ED_NAME_COL = 0, + ED_ICON_COL, + ED_VALUE_COL, + ED_N_COLS +}; + +static const guint row_count = 5; + +// {{{ Internal interfaces +// {{{ GTK+ Callbacks +static void style_name_edit_changed_cb (GtkEditable *widget, EdgeStyleEditor *editor); +static void decoration_combo_changed_cb (GtkComboBox *widget, EdgeStyleEditor *editor); +static void thickness_adjustment_changed_cb (GtkAdjustment *widget, EdgeStyleEditor *editor); +// }}} +// {{{ Notifications + +@interface EdgeStyleEditor (Notifications) +- (void) nameChangedTo:(NSString*)value; +- (void) edgeDecorationChangedTo:(EdgeDectorationStyle)value; +- (void) thicknessChangedTo:(double)value; +@end + +// }}} +// {{{ Private + +@interface EdgeStyleEditor (Private) +- (void) loadDecorationStylesInto:(GtkListStore*)list; +- (void) clearEdgeDecorationStyle; +- (void) setEdgeDecorationStyle:(EdgeDectorationStyle)value; +@end + +// }}} +// }}} +// {{{ API + +@implementation EdgeStyleEditor + +- (void) _addWidget:(GtkWidget*)w withLabel:(gchar *)label atRow:(guint)row { + NSAssert(row < row_count, @"row_count is wrong!"); + + GtkWidget *l = gtk_label_new (label); + gtk_misc_set_alignment (GTK_MISC (l), 0, 0.5); + gtk_widget_show (l); + gtk_widget_show (w); + + gtk_table_attach (table, l, + 0, 1, row, row+1, // l, r, t, b + GTK_FILL, // x opts + GTK_FILL | GTK_EXPAND, // y opts + 5, // x padding + 0); // y padding + + gtk_table_attach (table, w, + 1, 2, row, row+1, // l, r, t, b + GTK_FILL | GTK_EXPAND, // x opts + GTK_FILL | GTK_EXPAND, // y opts + 0, // x padding + 0); // y padding +} + +- (id) init { + self = [super init]; + + if (self != nil) { + style = nil; + table = GTK_TABLE (gtk_table_new (row_count, 2, FALSE)); + gtk_table_set_col_spacings (table, 6); + gtk_table_set_row_spacings (table, 6); + gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE); + blockSignals = NO; + + /** + * Name + */ + nameEdit = GTK_ENTRY (gtk_entry_new ()); + g_object_ref_sink (nameEdit); + [self _addWidget:GTK_WIDGET (nameEdit) + withLabel:"Name" + atRow:0]; + g_signal_connect (G_OBJECT (nameEdit), + "changed", + G_CALLBACK (style_name_edit_changed_cb), + self); + + + /** + * Edge decoration style + */ + GtkListStore *store = gtk_list_store_new (ED_N_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT); + [self loadDecorationStylesInto:store]; + + decorationCombo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store))); + g_object_unref (store); + GtkCellRenderer *cellRend = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (decorationCombo), + cellRend, + TRUE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (decorationCombo), cellRend, "pixbuf", ED_ICON_COL); + g_object_ref_sink (decorationCombo); + + [self _addWidget:GTK_WIDGET (decorationCombo) + withLabel:"Decoration" + atRow:1]; + g_signal_connect (G_OBJECT (decorationCombo), + "changed", + G_CALLBACK (decoration_combo_changed_cb), + self); + + + /** + * Thickness + */ + thicknessAdj = GTK_ADJUSTMENT (gtk_adjustment_new ( + 1.0, // value + 0.0, // lower + 50.0, // upper + 0.20, // step + 1.0, // page + 0.0)); // (irrelevant) + g_object_ref_sink (thicknessAdj); + GtkWidget *scaleSpin = gtk_spin_button_new (thicknessAdj, 0.0, 2); + [self _addWidget:scaleSpin + withLabel:"Thickness" + atRow:4]; + g_signal_connect (G_OBJECT (thicknessAdj), + "value-changed", + G_CALLBACK (thickness_adjustment_changed_cb), + self); + } + + return self; +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + g_object_unref (nameEdit); + g_object_unref (decorationCombo); + g_object_unref (thicknessAdj); + g_object_unref (table); + [style release]; + + [super dealloc]; +} + +- (EdgeStyle*) style { + return style; +} + +- (void) setStyle:(EdgeStyle*)s { + blockSignals = YES; + EdgeStyle *oldStyle = style; + style = [s retain]; + + if (style != nil) { + gtk_widget_set_sensitive (GTK_WIDGET (table), TRUE); + + gtk_entry_set_text(nameEdit, [[style name] UTF8String]); + + [self setEdgeDecorationStyle:[style decorationStyle]]; + + gtk_adjustment_set_value(thicknessAdj, [style thickness]); + } else { + gtk_entry_set_text(nameEdit, ""); + [self clearEdgeDecorationStyle]; + gtk_adjustment_set_value(thicknessAdj, 1.0); + gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE); + } + + [oldStyle release]; + blockSignals = NO; +} + +- (GtkWidget*) widget { + return GTK_WIDGET (table); +} + +@end + +// }}} +// {{{ Notifications + +@implementation EdgeStyleEditor (Notifications) +- (void) nameChangedTo:(NSString*)value { + [style setName:value]; +} + +- (void) edgeDecorationChangedTo:(EdgeDectorationStyle)value { + [style setDecorationStyle:value]; +} + +- (void) thicknessChangedTo:(double)value { + [style setThickness:(float)value]; +} +@end + +// }}} +// {{{ Private + +@implementation EdgeStyleEditor (Private) +- (BOOL) signalsBlocked { return blockSignals; } + +- (void) loadDecorationStylesInto:(GtkListStore*)list { + GtkTreeIter iter; + + GdkPixbuf *buf = gdk_pixbuf_from_pixdata (&ED_none_pixdata, FALSE, NULL); + gtk_list_store_append (list, &iter); + gtk_list_store_set (list, &iter, + ED_NAME_COL, "None", + ED_ICON_COL, buf, + ED_VALUE_COL, ED_None, + -1); + g_object_unref (buf); + + buf = gdk_pixbuf_from_pixdata (&ED_arrow_pixdata, FALSE, NULL); + gtk_list_store_append (list, &iter); + gtk_list_store_set (list, &iter, + ED_NAME_COL, "Arrow", + ED_ICON_COL, buf, + ED_VALUE_COL, ED_Arrow, + -1); + g_object_unref (buf); + + buf = gdk_pixbuf_from_pixdata (&ED_tick_pixdata, FALSE, NULL); + gtk_list_store_append (list, &iter); + gtk_list_store_set (list, &iter, + ED_NAME_COL, "Tick", + ED_ICON_COL, buf, + ED_VALUE_COL, ED_Tick, + -1); + g_object_unref (buf); +} + +- (void) clearEdgeDecorationStyle { + gtk_combo_box_set_active (decorationCombo, -1); +} + +- (void) setEdgeDecorationStyle:(EdgeDectorationStyle)value { + GtkTreeModel *model = gtk_combo_box_get_model (decorationCombo); + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + EdgeDectorationStyle ed_style; + gtk_tree_model_get (model, &iter, ED_VALUE_COL, &ed_style, -1); + if (ed_style == value) { + gtk_combo_box_set_active_iter (decorationCombo, &iter); + return; + } + } while (gtk_tree_model_iter_next (model, &iter)); + } +} +@end + +// }}} +// {{{ GTK+ callbacks + +static void style_name_edit_changed_cb (GtkEditable *widget, EdgeStyleEditor *editor) { + if ([editor signalsBlocked]) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + const gchar *contents = gtk_entry_get_text (GTK_ENTRY (widget)); + [editor nameChangedTo:[NSString stringWithUTF8String:contents]]; + + [pool drain]; +} + +static void decoration_combo_changed_cb (GtkComboBox *widget, EdgeStyleEditor *editor) { + if ([editor signalsBlocked]) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + GtkTreeIter iter; + gtk_combo_box_get_active_iter (widget, &iter); + EdgeDectorationStyle dec = ED_None; + gtk_tree_model_get (gtk_combo_box_get_model (widget), &iter, ED_VALUE_COL, &dec, -1); + [editor edgeDecorationChangedTo:dec]; + + [pool drain]; +} + +static void thickness_adjustment_changed_cb (GtkAdjustment *adj, EdgeStyleEditor *editor) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor thicknessChangedTo:gtk_adjustment_get_value (adj)]; + [pool drain]; +} + +// }}} + +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/EdgeStyleSelector.h b/tikzit/src/linux/EdgeStyleSelector.h new file mode 100644 index 0000000..935c9b7 --- /dev/null +++ b/tikzit/src/linux/EdgeStyleSelector.h @@ -0,0 +1,69 @@ +/* + * Copyright 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 +#import "StyleManager.h" + +@interface EdgeStyleSelector: NSObject { + GtkListStore *store; + GtkTreeView *view; + StyleManager *styleManager; + BOOL linkedToActiveStyle; + BOOL suppressSetActiveStyle; +} + +/*! + @property widget + @brief The GTK widget + */ +@property (readonly) GtkWidget *widget; + +/*! + @property manager + @brief The StyleManager to use. Default is [StyleManager manager] + */ +@property (retain) StyleManager *styleManager; + +/*! + @property linkedToActiveStyles + @brief Whether the current selection should be the same as the + style manager's active style + */ +@property (getter=isLinkedToActiveStyle) BOOL linkedToActiveStyle; + +/*! + @property selectedStyle + @brief The selected style. If linkedToActiveStyle is YES, this + will be the same as [manager activeStyle]. + + When this changes, a SelectedStyleChanged notification will be posted + */ +@property (assign) EdgeStyle *selectedStyle; + +/*! + * Initialise with the default style manager + */ +- (id) init; +/*! + * Initialise with the given style manager + */ +- (id) initWithStyleManager:(StyleManager*)m; + +@end + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/EdgeStyleSelector.m b/tikzit/src/linux/EdgeStyleSelector.m new file mode 100644 index 0000000..243d176 --- /dev/null +++ b/tikzit/src/linux/EdgeStyleSelector.m @@ -0,0 +1,454 @@ +/* + * Copyright 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 "EdgeStyleSelector.h" + +#import "CairoRenderContext.h" +#import "Shape.h" +#import "Shape+Render.h" +#import "ShapeNames.h" +#import "StyleManager.h" + +#import + +// {{{ Internal interfaces +// {{{ Signals +static void selection_changed_cb (GtkTreeSelection *sel, EdgeStyleSelector *mgr); +// }}} + +enum { + STYLES_NAME_COL = 0, + STYLES_ICON_COL, + STYLES_PTR_COL, + STYLES_N_COLS +}; + +@interface EdgeStyleSelector (Notifications) +- (void) stylesReplaced:(NSNotification*)notification; +- (void) styleAdded:(NSNotification*)notification; +- (void) styleRemoved:(NSNotification*)notification; +- (void) activeStyleChanged:(NSNotification*)notification; +- (void) stylePropertyChanged:(NSNotification*)notification; +- (void) shapeDictionaryReplaced:(NSNotification*)n; +- (void) selectionChanged; +@end + +@interface EdgeStyleSelector (Private) +- (void) clearModel; +- (cairo_surface_t*) createEdgeIconSurface; +- (GdkPixbuf*) pixbufOfEdgeInStyle:(EdgeStyle*)style; +- (GdkPixbuf*) pixbufFromSurface:(cairo_surface_t*)surface; +- (GdkPixbuf*) pixbufOfEdgeInStyle:(EdgeStyle*)style usingSurface:(cairo_surface_t*)surface; +- (void) addStyle:(EdgeStyle*)style; +- (void) postSelectedStyleChanged; +- (void) reloadStyles; +@end + +// }}} +// {{{ API + +@implementation EdgeStyleSelector + +- (id) init { + self = [self initWithStyleManager:[StyleManager manager]]; + return self; +} + +- (id) initWithStyleManager:(StyleManager*)m { + self = [super init]; + + if (self) { + styleManager = nil; + linkedToActiveStyle = YES; + + store = gtk_list_store_new (STYLES_N_COLS, + G_TYPE_STRING, + GDK_TYPE_PIXBUF, + G_TYPE_POINTER); + g_object_ref (store); + + view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (store))); + gtk_tree_view_set_headers_visible (view, FALSE); + g_object_ref (view); + + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + renderer = gtk_cell_renderer_pixbuf_new (); + column = gtk_tree_view_column_new_with_attributes ("Preview", + renderer, + "pixbuf", STYLES_ICON_COL, + NULL); + gtk_tree_view_append_column (view, column); + gtk_tree_view_set_tooltip_column (view, STYLES_NAME_COL); + + GtkTreeSelection *sel = gtk_tree_view_get_selection (view); + gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE); + + g_signal_connect (G_OBJECT (sel), + "changed", + G_CALLBACK (selection_changed_cb), + self); + + [self setStyleManager:m]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stylePropertyChanged:) + name:@"EdgeStylePropertyChanged" + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(shapeDictionaryReplaced:) + name:@"ShapeDictionaryReplaced" + object:[Shape class]]; + } + + return self; +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + g_object_unref (view); + [self clearModel]; + g_object_unref (store); + [styleManager release]; + + [super dealloc]; +} + +- (StyleManager*) styleManager { + return styleManager; +} + +- (void) setStyleManager:(StyleManager*)m { + if (m == nil) { + [NSException raise:NSInvalidArgumentException format:@"Style manager cannot be nil"]; + } + [m retain]; + + [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:styleManager]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stylesReplaced:) + name:@"EdgeStylesReplaced" + object:m]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(styleAdded:) + name:@"EdgeStyleAdded" + object:m]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(styleRemoved:) + name:@"EdgeStyleRemoved" + object:m]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(activeStyleChanged:) + name:@"ActiveEdgeStyleChanged" + object:m]; + + [styleManager release]; + styleManager = m; + + [self reloadStyles]; +} + +- (GtkWidget*) widget { + return GTK_WIDGET (view); +} + +- (BOOL) isLinkedToActiveStyle { + return linkedToActiveStyle; +} + +- (void) setLinkedToActiveStyle:(BOOL)linked { + linkedToActiveStyle = linked; + if (linkedToActiveStyle) { + EdgeStyle *style = [self selectedStyle]; + if ([styleManager activeEdgeStyle] != style) { + [self setSelectedStyle:[styleManager activeEdgeStyle]]; + } + } +} + +- (EdgeStyle*) selectedStyle { + GtkTreeSelection *sel = gtk_tree_view_get_selection (view); + GtkTreeIter iter; + + if (!gtk_tree_selection_get_selected (sel, NULL, &iter)) { + return nil; + } + + EdgeStyle *style = nil; + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, STYLES_PTR_COL, &style, -1); + + return style; +} + +- (void) setSelectedStyle:(EdgeStyle*)style { + GtkTreeSelection *sel = gtk_tree_view_get_selection (view); + + if (style == nil) { + gtk_tree_selection_unselect_all (sel); + return; + } + + 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, STYLES_PTR_COL, &rowStyle, -1); + if (style == rowStyle) { + gtk_tree_selection_unselect_all (sel); + GtkTreePath *path = gtk_tree_model_get_path (m, &row); + gtk_tree_selection_select_path (sel, path); + gtk_tree_path_free (path); + // styleManager.activeStyle will be updated by the GTK+ callback + return; + } + } while (gtk_tree_model_iter_next (m, &row)); + } +} + +@end + +// }}} +// {{{ Notifications + +@implementation EdgeStyleSelector (Notifications) + +- (void) stylesReplaced:(NSNotification*)notification { + [self reloadStyles]; +} + +- (void) styleAdded:(NSNotification*)notification { + [self addStyle:[[notification userInfo] objectForKey:@"style"]]; +} + +- (void) styleRemoved:(NSNotification*)notification { + EdgeStyle *style = [[notification userInfo] objectForKey:@"style"]; + + GtkTreeModel *model = GTK_TREE_MODEL (store); + GtkTreeIter row; + if (gtk_tree_model_get_iter_first (model, &row)) { + do { + EdgeStyle *rowStyle; + gtk_tree_model_get (model, &row, STYLES_PTR_COL, &rowStyle, -1); + if (style == rowStyle) { + gtk_list_store_remove (store, &row); + [rowStyle release]; + return; + } + } while (gtk_tree_model_iter_next (model, &row)); + } +} + +- (void) activeStyleChanged:(NSNotification*)notification { + if (linkedToActiveStyle) { + EdgeStyle *style = [self selectedStyle]; + if ([styleManager activeEdgeStyle] != style) { + [self setSelectedStyle:[styleManager activeEdgeStyle]]; + } + } +} + +- (void) stylePropertyChanged:(NSNotification*)notification { + EdgeStyle *style = [notification object]; + + GtkTreeModel *model = GTK_TREE_MODEL (store); + GtkTreeIter row; + if (gtk_tree_model_get_iter_first (model, &row)) { + do { + EdgeStyle *rowStyle; + gtk_tree_model_get (model, &row, STYLES_PTR_COL, &rowStyle, -1); + if (style == rowStyle) { + if ([@"name" isEqual:[[notification userInfo] objectForKey:@"propertyName"]]) { + gtk_list_store_set (store, &row, STYLES_NAME_COL, [[style name] UTF8String], -1); + } else if (![@"scale" isEqual:[[notification userInfo] objectForKey:@"propertyName"]]) { + GdkPixbuf *pixbuf = [self pixbufOfEdgeInStyle:style]; + gtk_list_store_set (store, &row, STYLES_ICON_COL, pixbuf, -1); + gdk_pixbuf_unref (pixbuf); + } + } + } while (gtk_tree_model_iter_next (model, &row)); + } +} + +- (void) shapeDictionaryReplaced:(NSNotification*)n { + [self reloadStyles]; +} + +- (void) selectionChanged { + if (linkedToActiveStyle) { + EdgeStyle *style = [self selectedStyle]; + if ([styleManager activeEdgeStyle] != style) { + [styleManager setActiveEdgeStyle:style]; + } + } + [self postSelectedStyleChanged]; +} +@end + +// }}} +// {{{ Private + +@implementation EdgeStyleSelector (Private) +- (void) clearModel { + [self setSelectedStyle:nil]; + GtkTreeModel *model = GTK_TREE_MODEL (store); + GtkTreeIter row; + if (gtk_tree_model_get_iter_first (model, &row)) { + do { + EdgeStyle *rowStyle; + gtk_tree_model_get (model, &row, STYLES_PTR_COL, &rowStyle, -1); + [rowStyle release]; + } while (gtk_tree_model_iter_next (model, &row)); + } + gtk_list_store_clear (store); +} + +- (cairo_surface_t*) createEdgeIconSurface { + return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 48, 18); +} + +- (GdkPixbuf*) pixbufOfEdgeInStyle:(EdgeStyle*)style { + cairo_surface_t *surface = [self createEdgeIconSurface]; + GdkPixbuf *pixbuf = [self pixbufOfEdgeInStyle:style usingSurface:surface]; + cairo_surface_destroy (surface); + return pixbuf; +} + +// Bring on GTK+3 and gdk_pixbuf_get_from_surface() +- (GdkPixbuf*) pixbufFromSurface:(cairo_surface_t*)surface { + cairo_surface_flush (surface); + + int width = cairo_image_surface_get_width (surface); + int height = cairo_image_surface_get_height (surface); + int stride = cairo_image_surface_get_stride (surface); + unsigned char *data = cairo_image_surface_get_data (surface); + + GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height); + unsigned char *pbdata = gdk_pixbuf_get_pixels (pixbuf); + int pbstride = gdk_pixbuf_get_rowstride (pixbuf); + + for (int y = 0; y < height; ++y) { + uint32_t *line = (uint32_t*)(data + y*stride); + unsigned char *pbline = pbdata + (y*pbstride); + for (int x = 0; x < width; ++x) { + uint32_t pixel = *(line + x); + unsigned char *pbpixel = pbline + (x*4); + // NB: We should un-pre-mult the alpha here. + // However, in our world, alpha is always + // on or off, so it doesn't really matter + pbpixel[3] = ((pixel & 0xff000000) >> 24); + pbpixel[0] = ((pixel & 0x00ff0000) >> 16); + pbpixel[1] = ((pixel & 0x0000ff00) >> 8); + pbpixel[2] = (pixel & 0x000000ff); + } + } + + return pixbuf; +} + +- (GdkPixbuf*) pixbufOfEdgeInStyle:(EdgeStyle*)style usingSurface:(cairo_surface_t*)surface { + Transformer *transformer = [Transformer defaultTransformer]; + [transformer setFlippedAboutXAxis:YES]; + + int width = cairo_image_surface_get_width (surface); + int height = cairo_image_surface_get_height (surface); + NSRect pixbufBounds = NSMakeRect(0.0, 0.0, width, height); + NSRect graphBounds = [transformer rectFromScreen:pixbufBounds]; + + NSPoint mid = NSMakePoint (NSMidX (graphBounds), NSMidY (graphBounds)); + NSPoint start = NSMakePoint (NSMinX (graphBounds) + 0.1f, mid.y); + NSPoint end = NSMakePoint (NSMaxX (graphBounds) - 0.1f, mid.y); + NSPoint midTan = NSMakePoint (mid.x + 0.1f, mid.y); + NSPoint leftNormal = NSMakePoint (mid.x, mid.y - 0.1f); + NSPoint rightNormal = NSMakePoint (mid.x, mid.y + 0.1f); + + CairoRenderContext *context = [[CairoRenderContext alloc] initForSurface:surface]; + [context clearSurface]; + + [context startPath]; + [context moveTo:[transformer toScreen:start]]; + [context lineTo:[transformer toScreen:end]]; + + switch ([style decorationStyle]) { + case ED_None: + break; + case ED_Tick: + [context moveTo:[transformer toScreen:leftNormal]]; + [context lineTo:[transformer toScreen:rightNormal]]; + break; + case ED_Arrow: + [context moveTo:[transformer toScreen:leftNormal]]; + [context lineTo:[transformer toScreen:midTan]]; + [context lineTo:[transformer toScreen:rightNormal]]; + break; + } + + [context setLineWidth:[style thickness]]; + [context strokePathWithColor:BlackRColor]; + + [context release]; + + return [self pixbufFromSurface:surface]; +} + +- (void) addStyle:(EdgeStyle*)style usingSurface:(cairo_surface_t*)surface { + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + + GdkPixbuf *pixbuf = [self pixbufOfEdgeInStyle:style usingSurface:surface]; + gtk_list_store_set (store, &iter, + STYLES_NAME_COL, [[style name] UTF8String], + STYLES_ICON_COL, pixbuf, + STYLES_PTR_COL, (gpointer)[style retain], + -1); + gdk_pixbuf_unref (pixbuf); +} + +- (void) addStyle:(EdgeStyle*)style { + cairo_surface_t *surface = [self createEdgeIconSurface]; + [self addStyle:style usingSurface:surface]; + cairo_surface_destroy (surface); +} + +- (void) postSelectedStyleChanged { + [[NSNotificationCenter defaultCenter] postNotificationName:@"SelectedStyleChanged" object:self]; +} + +- (void) reloadStyles { + [self clearModel]; + for (EdgeStyle *style in [styleManager edgeStyles]) { + [self addStyle:style]; + } +} +@end + +// }}} +// {{{ GTK+ callbacks + +static void selection_changed_cb (GtkTreeSelection *sel, EdgeStyleSelector *mgr) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [mgr selectionChanged]; + [pool drain]; +} +// }}} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker + diff --git a/tikzit/src/linux/EdgeStylesPalette.h b/tikzit/src/linux/EdgeStylesPalette.h new file mode 100644 index 0000000..a7d715b --- /dev/null +++ b/tikzit/src/linux/EdgeStylesPalette.h @@ -0,0 +1,46 @@ +/* + * Copyright 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 StyleManager; +@class EdgeStyleSelector; +@class EdgeStyleEditor; +@class TikzDocument; + +@interface EdgeStylesPalette: NSObject { + TikzDocument *document; + EdgeStyleSelector *selector; + EdgeStyleEditor *editor; + + GtkWidget *palette; + + GtkWidget *removeStyleButton; + GtkWidget *applyStyleButton; + GtkWidget *clearStyleButton; +} + +@property (retain) StyleManager *styleManager; +@property (retain) TikzDocument *document; +@property (readonly) GtkWidget *widget; + +- (id) initWithManager:(StyleManager*)m; + +@end + +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/EdgeStylesPalette.m b/tikzit/src/linux/EdgeStylesPalette.m new file mode 100644 index 0000000..bcb631e --- /dev/null +++ b/tikzit/src/linux/EdgeStylesPalette.m @@ -0,0 +1,283 @@ +/* + * Copyright 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 "EdgeStylesPalette.h" + +#import "EdgeStyleSelector.h" +#import "EdgeStyleEditor.h" +#import "StyleManager.h" +#import "TikzDocument.h" + +// {{{ Internal interfaces +// {{{ GTK+ Callbacks +static void add_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette); +static void remove_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette); +static void apply_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette); +static void clear_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette); +// }}} +// {{{ Notifications + +@interface EdgeStylesPalette (Notifications) +- (void) selectedStyleChanged:(NSNotification*)notification; +- (void) edgeSelectionChanged:(NSNotification*)n; +@end + +// }}} +// {{{ Private + +@interface EdgeStylesPalette (Private) +- (void) updateButtonState; +- (void) removeSelectedStyle; +- (void) applySelectedStyle; +- (void) clearSelectedStyle; +@end + +// }}} +// }}} +// {{{ API + +@implementation EdgeStylesPalette + +@synthesize widget=palette; + +- (id) init { + [self release]; + self = nil; + return nil; +} + +- (id) initWithManager:(StyleManager*)m { + self = [super init]; + + if (self) { + document = nil; + selector = [[EdgeStyleSelector alloc] initWithStyleManager:m]; + editor = [[EdgeStyleEditor alloc] init]; + + palette = gtk_vbox_new (FALSE, 0); + // FIXME: remove this line when we add edge styles + gtk_container_set_border_width (GTK_CONTAINER (palette), 6); + gtk_box_set_spacing (GTK_BOX (palette), 6); + g_object_ref_sink (palette); + + gtk_box_pack_start (GTK_BOX (palette), [editor widget], FALSE, FALSE, 0); + gtk_widget_show ([editor widget]); + GtkWidget *selectorFrame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (selectorFrame), [selector widget]); + gtk_box_pack_start (GTK_BOX (palette), selectorFrame, TRUE, TRUE, 0); + gtk_widget_show (selectorFrame); + gtk_widget_show ([selector widget]); + + GtkBox *buttonBox = GTK_BOX (gtk_hbox_new(FALSE, 5)); + gtk_box_pack_start (GTK_BOX (palette), GTK_WIDGET (buttonBox), FALSE, FALSE, 0); + + GtkBox *bbox1 = GTK_BOX (gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox1), FALSE, FALSE, 0); + + GtkWidget *addStyleButton = gtk_button_new (); + gtk_widget_set_tooltip_text (addStyleButton, "Add a new style"); + GtkWidget *addIcon = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (addStyleButton), addIcon); + gtk_box_pack_start (bbox1, addStyleButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (addStyleButton), + "clicked", + G_CALLBACK (add_style_button_cb), + self); + + removeStyleButton = gtk_button_new (); + g_object_ref_sink (removeStyleButton); + gtk_widget_set_tooltip_text (removeStyleButton, "Delete selected style"); + GtkWidget *removeIcon = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (removeStyleButton), removeIcon); + gtk_box_pack_start (bbox1, removeStyleButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (removeStyleButton), + "clicked", + G_CALLBACK (remove_style_button_cb), + self); + + GtkBox *bbox2 = GTK_BOX (gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox2), FALSE, FALSE, 0); + + applyStyleButton = gtk_button_new_with_label ("Apply"); + g_object_ref_sink (applyStyleButton); + gtk_widget_set_tooltip_text (applyStyleButton, "Apply style to selected edges"); + gtk_box_pack_start (bbox2, applyStyleButton, FALSE, FALSE, 5); + g_signal_connect (G_OBJECT (applyStyleButton), + "clicked", + G_CALLBACK (apply_style_button_cb), + self); + + clearStyleButton = gtk_button_new_with_label ("Clear"); + g_object_ref_sink (clearStyleButton); + gtk_widget_set_tooltip_text (clearStyleButton, "Clear style from selected edges"); + gtk_box_pack_start (bbox2, clearStyleButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (clearStyleButton), + "clicked", + G_CALLBACK (clear_style_button_cb), + self); + + gtk_widget_show_all (GTK_WIDGET (buttonBox)); + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(selectedStyleChanged:) + name:@"SelectedStyleChanged" + object:selector]; + + [self updateButtonState]; + } + + return self; +} + +- (StyleManager*) styleManager { + return [selector styleManager]; +} + +- (void) setStyleManager:(StyleManager*)m { + [selector setStyleManager:m]; +} + +- (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 (document != nil) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(edgeSelectionChanged:) + name:@"EdgeSelectionChanged" + object:[document pickSupport]]; + } +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [editor release]; + [selector release]; + [document release]; + + g_object_unref (palette); + g_object_unref (removeStyleButton); + g_object_unref (applyStyleButton); + g_object_unref (clearStyleButton); + + [super dealloc]; +} + +@end + +// }}} +// {{{ Notifications + +@implementation EdgeStylesPalette (Notifications) +- (void) selectedStyleChanged:(NSNotification*)notification { + [editor setStyle:[selector selectedStyle]]; + [self updateButtonState]; +} + +- (void) edgeSelectionChanged:(NSNotification*)n { + [self updateButtonState]; +} +@end + +// }}} +// {{{ Private + +@implementation EdgeStylesPalette (Private) +- (void) updateButtonState { + gboolean hasEdgeSelection = [[[document pickSupport] selectedEdges] count] > 0; + gboolean hasStyleSelection = [selector selectedStyle] != nil; + + gtk_widget_set_sensitive (applyStyleButton, hasEdgeSelection && hasStyleSelection); + gtk_widget_set_sensitive (clearStyleButton, hasEdgeSelection); + gtk_widget_set_sensitive (removeStyleButton, hasStyleSelection); +} + +- (void) removeSelectedStyle { + EdgeStyle *style = [selector selectedStyle]; + if (style) + [[selector styleManager] removeEdgeStyle:style]; +} + +- (void) applySelectedStyle { + [document startModifyEdges:[[document pickSupport] selectedEdges]]; + + EdgeStyle *style = [selector selectedStyle]; + for (Edge *edge in [[document pickSupport] selectedEdges]) { + [edge setStyle:style]; + } + + [document endModifyEdges]; +} + +- (void) clearSelectedStyle { + [document startModifyEdges:[[document pickSupport] selectedEdges]]; + + for (Edge *edge in [[document pickSupport] selectedEdges]) { + [edge setStyle:nil]; + } + + [document endModifyEdges]; +} + +@end + +// }}} +// {{{ GTK+ callbacks + +static void add_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + EdgeStyle *newStyle = [EdgeStyle defaultEdgeStyleWithName:@"newstyle"]; + [[palette styleManager] addEdgeStyle:newStyle]; + [[palette styleManager] setActiveEdgeStyle:newStyle]; + + [pool drain]; +} + +static void remove_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [palette removeSelectedStyle]; + [pool drain]; +} + +static void apply_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [palette applySelectedStyle]; + [pool drain]; +} + +static void clear_style_button_cb (GtkButton *widget, EdgeStylesPalette *palette) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [palette clearSelectedStyle]; + [pool drain]; +} + +// }}} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/MainWindow.h b/tikzit/src/linux/MainWindow.h index 8d3c583..09e531e 100644 --- a/tikzit/src/linux/MainWindow.h +++ b/tikzit/src/linux/MainWindow.h @@ -23,12 +23,12 @@ @class GraphRenderer; @class GraphInputHandler; @class Menu; -@class StylesPalette; -@class StyleManager; @class PropertyPane; @class Preambles; @class PreambleEditor; @class PreviewWindow; +@class StyleManager; +@class StylesPane; @class TikzDocument; /** @@ -46,17 +46,17 @@ GtkWindow *mainWindow; GtkTextBuffer *tikzBuffer; GtkStatusbar *statusBar; - GtkPaned *propsPane; - GtkPaned *stylesPane; - GtkPaned *graphPane; - GtkWidget *tikzDisp; + GtkPaned *propertyPaneSplitter; + GtkPaned *stylesPaneSplitter; + GtkPaned *tikzPaneSplitter; + GtkWidget *tikzPane; // Classes that manage parts of the window // (or other windows) Menu *menu; GraphRenderer *renderer; GraphInputHandler *inputHandler; - StylesPalette *stylesPalette; + StylesPane *stylesPane; PropertyPane *propertyPane; PreambleEditor *preambleWindow; PreviewWindow *previewWindow; diff --git a/tikzit/src/linux/MainWindow.m b/tikzit/src/linux/MainWindow.m index 5e5a81a..1feb922 100644 --- a/tikzit/src/linux/MainWindow.m +++ b/tikzit/src/linux/MainWindow.m @@ -37,7 +37,7 @@ #import "StyleManager.h" #import "Shape.h" #import "StyleManager+Storage.h" -#import "NodeStylesPalette.h" +#import "StylesPane.h" #import "SupportDir.h" #import "TikzDocument.h" #import "WidgetSurface.h" @@ -152,7 +152,7 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc [menu release]; [renderer release]; [inputHandler release]; - [stylesPalette release]; + [stylesPane release]; [propertyPane release]; [preambleWindow release]; [previewWindow release]; @@ -163,10 +163,10 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc g_object_unref (mainWindow); g_object_unref (tikzBuffer); g_object_unref (statusBar); - g_object_unref (propsPane); - g_object_unref (stylesPane); - g_object_unref (graphPane); - g_object_unref (tikzDisp); + g_object_unref (propertyPaneSplitter); + g_object_unref (stylesPaneSplitter); + g_object_unref (tikzPaneSplitter); + g_object_unref (tikzPane); [super dealloc]; } @@ -455,6 +455,7 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc [styleManager saveStylesUsingConfigurationName:@"styles"]; [propertyPane saveUiStateToConfig:configFile group:@"PropertyPane"]; + [stylesPane saveUiStateToConfig:configFile group:@"StylesPane"]; if (lastFolder != nil) { [configFile setStringEntry:@"lastFolder" inGroup:@"Paths" value:lastFolder]; @@ -592,41 +593,41 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc gtk_container_add (GTK_CONTAINER (toolbarBox), [menu toolbar]); gtk_widget_show ([menu toolbar]); - propsPane = GTK_PANED (gtk_hpaned_new ()); - g_object_ref_sink (propsPane); - gtk_widget_show (GTK_WIDGET (propsPane)); - gtk_box_pack_start (mainLayout, GTK_WIDGET (propsPane), TRUE, TRUE, 0); + propertyPaneSplitter = GTK_PANED (gtk_hpaned_new ()); + g_object_ref_sink (propertyPaneSplitter); + gtk_widget_show (GTK_WIDGET (propertyPaneSplitter)); + gtk_box_pack_start (mainLayout, GTK_WIDGET (propertyPaneSplitter), TRUE, TRUE, 0); propertyPane = [[PropertyPane alloc] init]; GtkWidget *propFrame = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (propFrame), [propertyPane widget]); - gtk_paned_pack1 (propsPane, propFrame, FALSE, TRUE); + gtk_paned_pack1 (propertyPaneSplitter, propFrame, FALSE, TRUE); gtk_widget_show (propFrame); gtk_widget_show ([propertyPane widget]); - stylesPane = GTK_PANED (gtk_hpaned_new ()); - g_object_ref_sink (stylesPane); - gtk_widget_show (GTK_WIDGET (stylesPane)); - gtk_paned_pack2 (propsPane, GTK_WIDGET (stylesPane), TRUE, TRUE); + stylesPaneSplitter = GTK_PANED (gtk_hpaned_new ()); + g_object_ref_sink (stylesPaneSplitter); + gtk_widget_show (GTK_WIDGET (stylesPaneSplitter)); + gtk_paned_pack2 (propertyPaneSplitter, GTK_WIDGET (stylesPaneSplitter), TRUE, TRUE); - stylesPalette = [[NodeStylesPalette alloc] initWithManager:styleManager]; + stylesPane = [[StylesPane alloc] initWithManager:styleManager]; GtkWidget *stylesFrame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (stylesFrame), [stylesPalette widget]); - gtk_paned_pack2 (stylesPane, stylesFrame, FALSE, TRUE); + gtk_container_add (GTK_CONTAINER (stylesFrame), [stylesPane widget]); + gtk_paned_pack2 (stylesPaneSplitter, stylesFrame, FALSE, TRUE); gtk_widget_show (stylesFrame); - gtk_widget_show ([stylesPalette widget]); + gtk_widget_show ([stylesPane widget]); - graphPane = GTK_PANED (gtk_vpaned_new ()); - g_object_ref_sink (graphPane); - gtk_widget_show (GTK_WIDGET (graphPane)); - gtk_paned_pack1 (stylesPane, GTK_WIDGET (graphPane), TRUE, TRUE); + tikzPaneSplitter = GTK_PANED (gtk_vpaned_new ()); + g_object_ref_sink (tikzPaneSplitter); + gtk_widget_show (GTK_WIDGET (tikzPaneSplitter)); + gtk_paned_pack1 (stylesPaneSplitter, GTK_WIDGET (tikzPaneSplitter), TRUE, TRUE); surface = [[WidgetSurface alloc] init]; gtk_widget_show ([surface widget]); GtkWidget *graphFrame = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (graphFrame), [surface widget]); gtk_widget_show (graphFrame); - gtk_paned_pack1 (graphPane, graphFrame, TRUE, TRUE); + gtk_paned_pack1 (tikzPaneSplitter, graphFrame, TRUE, TRUE); [surface setDefaultScale:50.0f]; [surface setKeepCentered:YES]; [surface setGrabsFocusOnClick:YES]; @@ -640,16 +641,16 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc GtkWidget *tikzScroller = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (tikzScroller); - tikzDisp = gtk_text_view_new_with_buffer (tikzBuffer); - gtk_text_view_set_left_margin (GTK_TEXT_VIEW (tikzDisp), 3); - gtk_text_view_set_right_margin (GTK_TEXT_VIEW (tikzDisp), 3); - g_object_ref_sink (tikzDisp); - gtk_widget_show (tikzDisp); - gtk_container_add (GTK_CONTAINER (tikzScroller), tikzDisp); + tikzPane = gtk_text_view_new_with_buffer (tikzBuffer); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (tikzPane), 3); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW (tikzPane), 3); + g_object_ref_sink (tikzPane); + gtk_widget_show (tikzPane); + gtk_container_add (GTK_CONTAINER (tikzScroller), tikzPane); GtkWidget *tikzFrame = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (tikzFrame), tikzScroller); gtk_widget_show (tikzFrame); - gtk_paned_pack2 (graphPane, tikzFrame, FALSE, TRUE); + gtk_paned_pack2 (tikzPaneSplitter, tikzFrame, FALSE, TRUE); statusBar = GTK_STATUSBAR (gtk_statusbar_new ()); gtk_widget_show (GTK_WIDGET (statusBar)); @@ -670,17 +671,18 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc } int panePos = [configFile integerEntry:@"toolboxWidth" inGroup:@"mainWindow"]; if (panePos > 0) { - gtk_paned_set_position (propsPane, panePos); + gtk_paned_set_position (propertyPaneSplitter, panePos); } panePos = [configFile integerEntry:@"styleboxWidth" inGroup:@"mainWindow"]; if (panePos > 0) { - gtk_paned_set_position (stylesPane, panePos); + gtk_paned_set_position (stylesPaneSplitter, panePos); } panePos = [configFile integerEntry:@"graphHeight" inGroup:@"mainWindow"]; if (panePos > 0) { - gtk_paned_set_position (graphPane, panePos); + gtk_paned_set_position (tikzPaneSplitter, panePos); } [propertyPane restoreUiStateFromConfig:configFile group:@"PropertyPane"]; + [stylesPane restoreUiStateFromConfig:configFile group:@"StylesPane"]; } - (void) _connectSignals { @@ -693,15 +695,15 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc "key-press-event", G_CALLBACK (tz_hijack_key_press), NULL); - g_signal_connect (G_OBJECT (propsPane), + g_signal_connect (G_OBJECT (propertyPaneSplitter), "notify::position", G_CALLBACK (toolbox_divider_position_changed_cb), self); - g_signal_connect (G_OBJECT (stylesPane), + g_signal_connect (G_OBJECT (stylesPaneSplitter), "notify::position", G_CALLBACK (stylebox_divider_position_changed_cb), self); - g_signal_connect (G_OBJECT (graphPane), + g_signal_connect (G_OBJECT (tikzPaneSplitter), "notify::position", G_CALLBACK (graph_divider_position_changed_cb), self); @@ -775,10 +777,10 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc if (hasError && !hasParseError) { gtk_statusbar_push (statusBar, 1, "Parse error"); GdkColor color = {0, 65535, 61184, 61184}; - gtk_widget_modify_base (tikzDisp, GTK_STATE_NORMAL, &color); + gtk_widget_modify_base (tikzPane, GTK_STATE_NORMAL, &color); } else if (!hasError && hasParseError) { gtk_statusbar_pop (statusBar, 1); - gtk_widget_modify_base (tikzDisp, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base (tikzPane, GTK_STATE_NORMAL, NULL); } hasParseError = hasError; } @@ -866,7 +868,7 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc document = newDoc; [renderer setDocument:document]; - [stylesPalette setDocument:document]; + [stylesPane setDocument:document]; [propertyPane setDocument:document]; #ifdef HAVE_POPPLER [previewWindow setDocument:document]; diff --git a/tikzit/src/linux/NodeStyleEditor.h b/tikzit/src/linux/NodeStyleEditor.h index 67219e8..9bde203 100644 --- a/tikzit/src/linux/NodeStyleEditor.h +++ b/tikzit/src/linux/NodeStyleEditor.h @@ -22,22 +22,22 @@ @interface NodeStyleEditor: NSObject { NodeStyle *style; - GtkTable *table; + GtkTable *table; GtkEntry *nameEdit; GtkComboBox *shapeNameCombo; GtkColorButton *strokeColorButton; GtkWidget *makeStrokeTexSafeButton; GtkColorButton *fillColorButton; GtkWidget *makeFillTexSafeButton; - GtkAdjustment *scaleAdj; - BOOL blockSignals; + GtkAdjustment *scaleAdj; + BOOL blockSignals; } -@property (retain) NodeStyle *style; +@property (retain) NodeStyle *style; @property (readonly) GtkWidget *widget; - (id) init; @end -// vim:ft=objc:ts=4:noet:sts=4:sw=4 +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/NodeStyleEditor.m b/tikzit/src/linux/NodeStyleEditor.m index 32416be..febbf3c 100644 --- a/tikzit/src/linux/NodeStyleEditor.m +++ b/tikzit/src/linux/NodeStyleEditor.m @@ -60,189 +60,189 @@ static void scale_adjustment_changed_cb (GtkAdjustment *widget, NodeStyleEditor @implementation NodeStyleEditor - (void) _addWidget:(GtkWidget*)w withLabel:(gchar *)label atRow:(guint)row { - NSAssert(row < row_count, @"row_count is wrong!"); - - GtkWidget *l = gtk_label_new (label); - gtk_misc_set_alignment (GTK_MISC (l), 0, 0.5); - gtk_widget_show (l); - gtk_widget_show (w); - - gtk_table_attach (table, l, - 0, 1, row, row+1, // l, r, t, b - GTK_FILL, // x opts - GTK_FILL | GTK_EXPAND, // y opts - 5, // x padding - 0); // y padding - - gtk_table_attach (table, w, - 1, 2, row, row+1, // l, r, t, b - GTK_FILL | GTK_EXPAND, // x opts - GTK_FILL | GTK_EXPAND, // y opts - 0, // x padding - 0); // y padding + NSAssert(row < row_count, @"row_count is wrong!"); + + GtkWidget *l = gtk_label_new (label); + gtk_misc_set_alignment (GTK_MISC (l), 0, 0.5); + gtk_widget_show (l); + gtk_widget_show (w); + + gtk_table_attach (table, l, + 0, 1, row, row+1, // l, r, t, b + GTK_FILL, // x opts + GTK_FILL | GTK_EXPAND, // y opts + 5, // x padding + 0); // y padding + + gtk_table_attach (table, w, + 1, 2, row, row+1, // l, r, t, b + GTK_FILL | GTK_EXPAND, // x opts + GTK_FILL | GTK_EXPAND, // y opts + 0, // x padding + 0); // y padding } - (GtkWidget*) _createMakeColorTexSafeButton:(NSString*)type { - GtkWidget *b = gtk_button_new (); - GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON); - gtk_widget_show (icon); - gtk_container_add (GTK_CONTAINER (b), icon); - NSString *ttip = [NSString stringWithFormat:@"The %@ colour is not a predefined TeX colour.\nClick here to choose the nearest TeX-safe colour.", type]; - gtk_widget_set_tooltip_text (b, [ttip UTF8String]); - return b; + GtkWidget *b = gtk_button_new (); + GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON); + gtk_widget_show (icon); + gtk_container_add (GTK_CONTAINER (b), icon); + NSString *ttip = [NSString stringWithFormat:@"The %@ colour is not a predefined TeX colour.\nClick here to choose the nearest TeX-safe colour.", type]; + gtk_widget_set_tooltip_text (b, [ttip UTF8String]); + return b; } - (id) init { - self = [super init]; - - if (self != nil) { - style = nil; - table = GTK_TABLE (gtk_table_new (row_count, 2, FALSE)); - gtk_table_set_col_spacings (table, 6); - gtk_table_set_row_spacings (table, 6); - gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE); - blockSignals = NO; - - /** - * Name - */ - nameEdit = GTK_ENTRY (gtk_entry_new ()); - g_object_ref_sink (nameEdit); - [self _addWidget:GTK_WIDGET (nameEdit) - withLabel:"Name" - atRow:0]; - g_signal_connect (G_OBJECT (nameEdit), - "changed", - G_CALLBACK (style_name_edit_changed_cb), - self); - - - /** - * Shape - */ - GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); - shapeNameCombo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store))); - GtkCellRenderer *cellRend = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (shapeNameCombo), - cellRend, - TRUE); - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (shapeNameCombo), cellRend, "text", 0); - g_object_ref_sink (shapeNameCombo); - [self _addWidget:GTK_WIDGET (shapeNameCombo) - withLabel:"Shape" - atRow:1]; - g_signal_connect (G_OBJECT (shapeNameCombo), - "changed", - G_CALLBACK (style_shape_combo_changed_cb), - self); - - - /** - * Stroke colour - */ - GtkWidget *strokeBox = gtk_hbox_new (FALSE, 0); - [self _addWidget:strokeBox - withLabel:"Stroke colour" - atRow:2]; - strokeColorButton = GTK_COLOR_BUTTON (gtk_color_button_new ()); - g_object_ref_sink (strokeColorButton); - gtk_widget_show (GTK_WIDGET (strokeColorButton)); - gtk_box_pack_start (GTK_BOX (strokeBox), GTK_WIDGET (strokeColorButton), - FALSE, FALSE, 0); - makeStrokeTexSafeButton = [self _createMakeColorTexSafeButton:@"stroke"]; - g_object_ref_sink (makeStrokeTexSafeButton); - gtk_box_pack_start (GTK_BOX (strokeBox), makeStrokeTexSafeButton, - FALSE, FALSE, 0); - g_signal_connect (G_OBJECT (strokeColorButton), - "color-set", - G_CALLBACK (stroke_color_changed_cb), - self); - g_signal_connect (G_OBJECT (makeStrokeTexSafeButton), - "clicked", - G_CALLBACK (make_stroke_safe_button_clicked_cb), - self); - - - /** - * Fill colour - */ - GtkWidget *fillBox = gtk_hbox_new (FALSE, 0); - [self _addWidget:fillBox - withLabel:"Fill colour" - atRow:3]; - fillColorButton = GTK_COLOR_BUTTON (gtk_color_button_new ()); - g_object_ref_sink (fillColorButton); - gtk_widget_show (GTK_WIDGET (fillColorButton)); - gtk_box_pack_start (GTK_BOX (fillBox), GTK_WIDGET (fillColorButton), - FALSE, FALSE, 0); - makeFillTexSafeButton = [self _createMakeColorTexSafeButton:@"fill"]; - g_object_ref_sink (makeFillTexSafeButton); - gtk_box_pack_start (GTK_BOX (fillBox), makeFillTexSafeButton, - FALSE, FALSE, 0); - g_signal_connect (G_OBJECT (fillColorButton), - "color-set", - G_CALLBACK (fill_color_changed_cb), - self); - g_signal_connect (G_OBJECT (makeFillTexSafeButton), - "clicked", - G_CALLBACK (make_fill_safe_button_clicked_cb), - self); - - - /** - * Scale - */ - scaleAdj = GTK_ADJUSTMENT (gtk_adjustment_new ( - 1.0, // value - 0.0, // lower - 50.0, // upper - 0.20, // step - 1.0, // page - 0.0)); // (irrelevant) - g_object_ref_sink (scaleAdj); - GtkWidget *scaleSpin = gtk_spin_button_new (scaleAdj, 0.0, 2); - [self _addWidget:scaleSpin - withLabel:"Scale" - atRow:4]; - g_signal_connect (G_OBJECT (scaleAdj), - "value-changed", - G_CALLBACK (scale_adjustment_changed_cb), - self); - - [self loadShapeNames]; + self = [super init]; + + if (self != nil) { + style = nil; + table = GTK_TABLE (gtk_table_new (row_count, 2, FALSE)); + gtk_table_set_col_spacings (table, 6); + gtk_table_set_row_spacings (table, 6); + gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE); + blockSignals = NO; + + /** + * Name + */ + nameEdit = GTK_ENTRY (gtk_entry_new ()); + g_object_ref_sink (nameEdit); + [self _addWidget:GTK_WIDGET (nameEdit) + withLabel:"Name" + atRow:0]; + g_signal_connect (G_OBJECT (nameEdit), + "changed", + G_CALLBACK (style_name_edit_changed_cb), + self); + + + /** + * Shape + */ + GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING); + shapeNameCombo = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store))); + GtkCellRenderer *cellRend = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (shapeNameCombo), + cellRend, + TRUE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (shapeNameCombo), cellRend, "text", 0); + g_object_ref_sink (shapeNameCombo); + [self _addWidget:GTK_WIDGET (shapeNameCombo) + withLabel:"Shape" + atRow:1]; + g_signal_connect (G_OBJECT (shapeNameCombo), + "changed", + G_CALLBACK (style_shape_combo_changed_cb), + self); + + + /** + * Stroke colour + */ + GtkWidget *strokeBox = gtk_hbox_new (FALSE, 0); + [self _addWidget:strokeBox + withLabel:"Stroke colour" + atRow:2]; + strokeColorButton = GTK_COLOR_BUTTON (gtk_color_button_new ()); + g_object_ref_sink (strokeColorButton); + gtk_widget_show (GTK_WIDGET (strokeColorButton)); + gtk_box_pack_start (GTK_BOX (strokeBox), GTK_WIDGET (strokeColorButton), + FALSE, FALSE, 0); + makeStrokeTexSafeButton = [self _createMakeColorTexSafeButton:@"stroke"]; + g_object_ref_sink (makeStrokeTexSafeButton); + gtk_box_pack_start (GTK_BOX (strokeBox), makeStrokeTexSafeButton, + FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (strokeColorButton), + "color-set", + G_CALLBACK (stroke_color_changed_cb), + self); + g_signal_connect (G_OBJECT (makeStrokeTexSafeButton), + "clicked", + G_CALLBACK (make_stroke_safe_button_clicked_cb), + self); + + + /** + * Fill colour + */ + GtkWidget *fillBox = gtk_hbox_new (FALSE, 0); + [self _addWidget:fillBox + withLabel:"Fill colour" + atRow:3]; + fillColorButton = GTK_COLOR_BUTTON (gtk_color_button_new ()); + g_object_ref_sink (fillColorButton); + gtk_widget_show (GTK_WIDGET (fillColorButton)); + gtk_box_pack_start (GTK_BOX (fillBox), GTK_WIDGET (fillColorButton), + FALSE, FALSE, 0); + makeFillTexSafeButton = [self _createMakeColorTexSafeButton:@"fill"]; + g_object_ref_sink (makeFillTexSafeButton); + gtk_box_pack_start (GTK_BOX (fillBox), makeFillTexSafeButton, + FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (fillColorButton), + "color-set", + G_CALLBACK (fill_color_changed_cb), + self); + g_signal_connect (G_OBJECT (makeFillTexSafeButton), + "clicked", + G_CALLBACK (make_fill_safe_button_clicked_cb), + self); + + + /** + * Scale + */ + scaleAdj = GTK_ADJUSTMENT (gtk_adjustment_new ( + 1.0, // value + 0.0, // lower + 50.0, // upper + 0.20, // step + 1.0, // page + 0.0)); // (irrelevant) + g_object_ref_sink (scaleAdj); + GtkWidget *scaleSpin = gtk_spin_button_new (scaleAdj, 0.0, 2); + [self _addWidget:scaleSpin + withLabel:"Scale" + atRow:4]; + g_signal_connect (G_OBJECT (scaleAdj), + "value-changed", + G_CALLBACK (scale_adjustment_changed_cb), + self); + + [self loadShapeNames]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shapeDictionaryReplaced:) name:@"ShapeDictionaryReplaced" object:[Shape class]]; - } + } - return self; + return self; } - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - g_object_unref (nameEdit); - g_object_unref (shapeNameCombo); + g_object_unref (nameEdit); + g_object_unref (shapeNameCombo); g_object_unref (strokeColorButton); g_object_unref (makeStrokeTexSafeButton); g_object_unref (fillColorButton); g_object_unref (makeFillTexSafeButton); - g_object_unref (scaleAdj); - g_object_unref (table); - [style release]; + g_object_unref (scaleAdj); + g_object_unref (table); + [style release]; - [super dealloc]; + [super dealloc]; } - (NodeStyle*) style { - return style; + return style; } - (void) setStyle:(NodeStyle*)s { - blockSignals = YES; - NodeStyle *oldStyle = style; - style = [s retain]; + blockSignals = YES; + NodeStyle *oldStyle = style; + style = [s retain]; if (style != nil) { gtk_widget_set_sensitive (GTK_WIDGET (table), TRUE); @@ -256,7 +256,7 @@ static void scale_adjustment_changed_cb (GtkAdjustment *widget, NodeStyleEditor gtk_widget_set_visible (makeStrokeTexSafeButton, ([[style strokeColorRGB] name] == nil)); - c = [style fillColor]; + c = [style fillColor]; gtk_color_button_set_color(fillColorButton, &c); gtk_widget_set_visible (makeFillTexSafeButton, ([[style fillColorRGB] name] == nil)); @@ -271,12 +271,12 @@ static void scale_adjustment_changed_cb (GtkAdjustment *widget, NodeStyleEditor gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE); } - [oldStyle release]; - blockSignals = NO; + [oldStyle release]; + blockSignals = NO; } - (GtkWidget*) widget { - return GTK_WIDGET (table); + return GTK_WIDGET (table); } @end @@ -286,54 +286,54 @@ static void scale_adjustment_changed_cb (GtkAdjustment *widget, NodeStyleEditor @implementation NodeStyleEditor (Notifications) - (void) shapeDictionaryReplaced:(NSNotification*)n { - blockSignals = YES; + blockSignals = YES; [self loadShapeNames]; [self setActiveShapeName:[style shapeName]]; - blockSignals = NO; + blockSignals = NO; } - (void) nameChangedTo:(NSString*)value { - [style setName:value]; + [style setName:value]; } - (void) shapeNameChangedTo:(NSString*)value { - [style setShapeName:value]; + [style setShapeName:value]; } - (void) strokeColorChangedTo:(GdkColor)value { - [style setStrokeColor:value]; - gtk_widget_set_visible (makeStrokeTexSafeButton, - [[style strokeColorRGB] name] == nil); + [style setStrokeColor:value]; + gtk_widget_set_visible (makeStrokeTexSafeButton, + [[style strokeColorRGB] name] == nil); } - (void) makeStrokeColorTexSafe { - if (style != nil) { - [[style strokeColorRGB] setToClosestHashed]; - GdkColor color = [style strokeColor]; - gtk_color_button_set_color(strokeColorButton, &color); - gtk_widget_set_visible (makeStrokeTexSafeButton, FALSE); - } + if (style != nil) { + [[style strokeColorRGB] setToClosestHashed]; + GdkColor color = [style strokeColor]; + gtk_color_button_set_color(strokeColorButton, &color); + gtk_widget_set_visible (makeStrokeTexSafeButton, FALSE); + } } - (void) fillColorChangedTo:(GdkColor)value { - [style setFillColor:value]; - gtk_widget_set_visible (makeFillTexSafeButton, - [[style fillColorRGB] name] == nil); + [style setFillColor:value]; + gtk_widget_set_visible (makeFillTexSafeButton, + [[style fillColorRGB] name] == nil); } - (void) makeFillColorTexSafe { - if (style != nil) { - [[style fillColorRGB] setToClosestHashed]; - GdkColor color = [style fillColor]; - gtk_color_button_set_color(fillColorButton, &color); - gtk_widget_set_visible (makeFillTexSafeButton, FALSE); - } + if (style != nil) { + [[style fillColorRGB] setToClosestHashed]; + GdkColor color = [style fillColor]; + gtk_color_button_set_color(fillColorButton, &color); + gtk_widget_set_visible (makeFillTexSafeButton, FALSE); + } } - (void) scaleChangedTo:(double)value { - [style setScale:value]; + [style setScale:value]; } @end @@ -390,62 +390,62 @@ static void scale_adjustment_changed_cb (GtkAdjustment *widget, NodeStyleEditor // {{{ GTK+ callbacks static void style_name_edit_changed_cb (GtkEditable *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - const gchar *contents = gtk_entry_get_text (GTK_ENTRY (widget)); - [editor nameChangedTo:[NSString stringWithUTF8String:contents]]; + const gchar *contents = gtk_entry_get_text (GTK_ENTRY (widget)); + [editor nameChangedTo:[NSString stringWithUTF8String:contents]]; [pool drain]; } static void style_shape_combo_changed_cb (GtkComboBox *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - GtkTreeIter iter; - gtk_combo_box_get_active_iter (widget, &iter); - gchar *shapeName = NULL; - gtk_tree_model_get (gtk_combo_box_get_model (widget), &iter, 0, &shapeName, -1); - [editor shapeNameChangedTo:[NSString stringWithUTF8String:shapeName]]; - g_free (shapeName); + GtkTreeIter iter; + gtk_combo_box_get_active_iter (widget, &iter); + gchar *shapeName = NULL; + gtk_tree_model_get (gtk_combo_box_get_model (widget), &iter, 0, &shapeName, -1); + [editor shapeNameChangedTo:[NSString stringWithUTF8String:shapeName]]; + g_free (shapeName); [pool drain]; } static void stroke_color_changed_cb (GtkColorButton *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GdkColor color; gtk_color_button_get_color (widget, &color); - [editor strokeColorChangedTo:color]; + [editor strokeColorChangedTo:color]; [pool drain]; } static void fill_color_changed_cb (GtkColorButton *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GdkColor color; gtk_color_button_get_color (widget, &color); - [editor fillColorChangedTo:color]; + [editor fillColorChangedTo:color]; [pool drain]; } static void make_stroke_safe_button_clicked_cb (GtkButton *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [editor makeStrokeColorTexSafe]; @@ -453,8 +453,8 @@ static void make_stroke_safe_button_clicked_cb (GtkButton *widget, NodeStyleEdit } static void make_fill_safe_button_clicked_cb (GtkButton *widget, NodeStyleEditor *editor) { - if ([editor signalsBlocked]) - return; + if ([editor signalsBlocked]) + return; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [editor makeFillColorTexSafe]; @@ -463,10 +463,10 @@ static void make_fill_safe_button_clicked_cb (GtkButton *widget, NodeStyleEditor static void scale_adjustment_changed_cb (GtkAdjustment *adj, NodeStyleEditor *editor) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [editor scaleChangedTo:gtk_adjustment_get_value (adj)]; + [editor scaleChangedTo:gtk_adjustment_get_value (adj)]; [pool drain]; } // }}} -// vim:ft=objc:ts=4:noet:sts=4:sw=4:foldmethod=marker +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/NodeStyleSelector.h b/tikzit/src/linux/NodeStyleSelector.h index c6c8833..894d71e 100644 --- a/tikzit/src/linux/NodeStyleSelector.h +++ b/tikzit/src/linux/NodeStyleSelector.h @@ -56,21 +56,13 @@ @property (assign) NodeStyle *selectedStyle; /*! - * Initialise with the default style manager and a new icon view widget + * Initialise with the default style manager */ - (id) init; /*! - * Initialise with the default style manager and the given icon view widget - */ -- (id) initWithIconView:(GtkIconView*)view; -/*! - * Initialise with the given style manager and a new icon view widget + * Initialise with the given style manager */ - (id) initWithStyleManager:(StyleManager*)m; -/*! - * Initialise with the given style manager and icon view widget - */ -- (id) initWithIconView:(GtkIconView*)view andStyleManager:(StyleManager*)m; @end diff --git a/tikzit/src/linux/NodeStyleSelector.m b/tikzit/src/linux/NodeStyleSelector.m index 5539b93..395d9ca 100644 --- a/tikzit/src/linux/NodeStyleSelector.m +++ b/tikzit/src/linux/NodeStyleSelector.m @@ -23,8 +23,9 @@ #import "ShapeNames.h" #import "StyleManager.h" -#import "gdk-pixbuf/gdk-pixbuf.h" +#import +// {{{ Internal interfaces // {{{ Signals static void selection_changed_cb (GtkIconView *widget, NodeStyleSelector *mgr); // }}} @@ -56,7 +57,9 @@ enum { - (void) reloadStyles; @end +// }}} // {{{ API + @implementation NodeStyleSelector - (id) init { @@ -64,17 +67,7 @@ enum { return self; } -- (id) initWithIconView:(GtkIconView*)view { - self = [self initWithIconView:GTK_ICON_VIEW (gtk_icon_view_new ()) andStyleManager:[StyleManager manager]]; - return self; -} - - (id) initWithStyleManager:(StyleManager*)m { - self = [self initWithIconView:GTK_ICON_VIEW (gtk_icon_view_new ()) andStyleManager:m]; - return self; -} - -- (id) initWithIconView:(GtkIconView*)v andStyleManager:(StyleManager*)m { self = [super init]; if (self) { @@ -87,7 +80,7 @@ enum { G_TYPE_POINTER); g_object_ref (store); - view = v; + view = GTK_ICON_VIEW (gtk_icon_view_new ()); g_object_ref (view); gtk_icon_view_set_model (view, GTK_TREE_MODEL (store)); @@ -115,6 +108,16 @@ enum { return self; } +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + g_object_unref (view); + [self clearModel]; + g_object_unref (store); + [styleManager release]; + + [super dealloc]; +} + - (void) clearModel { [self setSelectedStyle:nil]; GtkTreeModel *model = GTK_TREE_MODEL (store); @@ -226,20 +229,11 @@ enum { } } -- (void) dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - g_object_unref (view); - [self clearModel]; - g_object_unref (store); - [styleManager release]; - - [super dealloc]; -} - @end -// }}} +// }}} // {{{ Notifications + @implementation NodeStyleSelector (Notifications) - (void) stylesReplaced:(NSNotification*)notification { @@ -313,9 +307,10 @@ enum { [self postSelectedStyleChanged]; } @end -// }}} +// }}} // {{{ Private + @implementation NodeStyleSelector (Private) - (cairo_surface_t*) createNodeIconSurface { return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 24, 24); @@ -416,9 +411,10 @@ enum { } } @end -// }}} +// }}} // {{{ GTK+ callbacks + static void selection_changed_cb (GtkIconView *view, NodeStyleSelector *mgr) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [mgr selectionChanged]; @@ -426,4 +422,4 @@ static void selection_changed_cb (GtkIconView *view, NodeStyleSelector *mgr) { } // }}} -// vim:ft=objc:ts=8:et:sts=4:sw=4 +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/NodeStylesPalette.h b/tikzit/src/linux/NodeStylesPalette.h index dfecc17..0185857 100644 --- a/tikzit/src/linux/NodeStylesPalette.h +++ b/tikzit/src/linux/NodeStylesPalette.h @@ -35,12 +35,12 @@ GtkWidget *clearStyleButton; } -@property (retain) StyleManager *styleManager; -@property (retain) TikzDocument *document; -@property (readonly) GtkWidget *widget; +@property (retain) StyleManager *styleManager; +@property (retain) TikzDocument *document; +@property (readonly) GtkWidget *widget; - (id) initWithManager:(StyleManager*)m; @end -// vim:ft=objc:ts=4:noet:sts=4:sw=4 +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/NodeStylesPalette.m b/tikzit/src/linux/NodeStylesPalette.m index 24a5729..d5ac2e1 100644 --- a/tikzit/src/linux/NodeStylesPalette.m +++ b/tikzit/src/linux/NodeStylesPalette.m @@ -66,27 +66,25 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette if (self) { document = nil; selector = [[NodeStyleSelector alloc] initWithStyleManager:m]; - editor = [[NodeStyleEditor alloc] init]; + editor = [[NodeStyleEditor alloc] init]; palette = gtk_vbox_new (FALSE, 0); - // FIXME: remove this line when we add edge styles - gtk_container_set_border_width (GTK_CONTAINER (palette), 6); - gtk_box_set_spacing (GTK_BOX (palette), 6); - g_object_ref_sink (palette); - - gtk_box_pack_start (GTK_BOX (palette), [editor widget], FALSE, FALSE, 0); - gtk_widget_show ([editor widget]); - GtkWidget *selectorFrame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (selectorFrame), [selector widget]); - gtk_box_pack_start (GTK_BOX (palette), selectorFrame, TRUE, TRUE, 0); - gtk_widget_show (selectorFrame); - gtk_widget_show ([selector widget]); + gtk_box_set_spacing (GTK_BOX (palette), 6); + g_object_ref_sink (palette); + + gtk_box_pack_start (GTK_BOX (palette), [editor widget], FALSE, FALSE, 0); + gtk_widget_show ([editor widget]); + GtkWidget *selectorFrame = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (selectorFrame), [selector widget]); + gtk_box_pack_start (GTK_BOX (palette), selectorFrame, TRUE, TRUE, 0); + gtk_widget_show (selectorFrame); + gtk_widget_show ([selector widget]); GtkBox *buttonBox = GTK_BOX (gtk_hbox_new(FALSE, 5)); - gtk_box_pack_start (GTK_BOX (palette), GTK_WIDGET (buttonBox), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (palette), GTK_WIDGET (buttonBox), FALSE, FALSE, 0); GtkBox *bbox1 = GTK_BOX (gtk_hbox_new(FALSE, 0)); - gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox1), FALSE, FALSE, 0); + gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox1), FALSE, FALSE, 0); GtkWidget *addStyleButton = gtk_button_new (); gtk_widget_set_tooltip_text (addStyleButton, "Add a new style"); @@ -99,7 +97,7 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette self); removeStyleButton = gtk_button_new (); - g_object_ref_sink (removeStyleButton); + g_object_ref_sink (removeStyleButton); gtk_widget_set_tooltip_text (removeStyleButton, "Delete selected style"); GtkWidget *removeIcon = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON); gtk_container_add (GTK_CONTAINER (removeStyleButton), removeIcon); @@ -110,10 +108,10 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette self); GtkBox *bbox2 = GTK_BOX (gtk_hbox_new(FALSE, 0)); - gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox2), FALSE, FALSE, 0); + gtk_box_pack_start (buttonBox, GTK_WIDGET (bbox2), FALSE, FALSE, 0); applyStyleButton = gtk_button_new_with_label ("Apply"); - g_object_ref_sink (applyStyleButton); + g_object_ref_sink (applyStyleButton); gtk_widget_set_tooltip_text (applyStyleButton, "Apply style to selected nodes"); gtk_box_pack_start (bbox2, applyStyleButton, FALSE, FALSE, 5); g_signal_connect (G_OBJECT (applyStyleButton), @@ -122,7 +120,7 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette self); clearStyleButton = gtk_button_new_with_label ("Clear"); - g_object_ref_sink (clearStyleButton); + g_object_ref_sink (clearStyleButton); gtk_widget_set_tooltip_text (clearStyleButton, "Clear style from selected nodes"); gtk_box_pack_start (bbox2, clearStyleButton, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (clearStyleButton), @@ -130,14 +128,14 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette G_CALLBACK (clear_style_button_cb), self); - gtk_widget_show_all (GTK_WIDGET (buttonBox)); + gtk_widget_show_all (GTK_WIDGET (buttonBox)); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectedStyleChanged:) name:@"SelectedStyleChanged" object:selector]; - [self updateButtonState]; + [self updateButtonState]; } return self; @@ -179,10 +177,10 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette [editor release]; [selector release]; [document release]; - g_object_unref (palette); - g_object_unref (removeStyleButton); - g_object_unref (applyStyleButton); - g_object_unref (clearStyleButton); + g_object_unref (palette); + g_object_unref (removeStyleButton); + g_object_unref (applyStyleButton); + g_object_unref (clearStyleButton); [super dealloc]; } @@ -194,7 +192,7 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette @implementation NodeStylesPalette (Notifications) - (void) selectedStyleChanged:(NSNotification*)notification { - [editor setStyle:[selector selectedStyle]]; + [editor setStyle:[selector selectedStyle]]; [self updateButtonState]; } @@ -213,7 +211,7 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette gtk_widget_set_sensitive (applyStyleButton, hasNodeSelection && hasStyleSelection); gtk_widget_set_sensitive (clearStyleButton, hasNodeSelection); - gtk_widget_set_sensitive (removeStyleButton, hasStyleSelection); + gtk_widget_set_sensitive (removeStyleButton, hasStyleSelection); } - (void) removeSelectedStyle { @@ -278,4 +276,4 @@ static void clear_style_button_cb (GtkButton *widget, NodeStylesPalette *palette // }}} -// vim:ft=objc:ts=4:noet:sts=4:sw=4:foldmethod=marker +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/PropertyPane.h b/tikzit/src/linux/PropertyPane.h index 5b6ef1b..30f8e5a 100644 --- a/tikzit/src/linux/PropertyPane.h +++ b/tikzit/src/linux/PropertyPane.h @@ -19,8 +19,8 @@ #import #import "Configuration.h" #import "TikzDocument.h" -#import "PropertyListEditor.h" +@class PropertyListEditor; @class GraphPropertyDelegate; @class NodePropertyDelegate; @class EdgePropertyDelegate; @@ -52,16 +52,14 @@ GtkEntry *edgeNodeLabelEntry; } -@property (readonly) GtkWidget *widget; +@property (readonly) GtkWidget *widget; +@property (retain) TikzDocument *document; - (id) init; -- (TikzDocument*) document; -- (void) setDocument:(TikzDocument*)doc; - - (void) restoreUiStateFromConfig:(Configuration*)file group:(NSString*)group; - (void) saveUiStateToConfig:(Configuration*)file group:(NSString*)group; @end -// vim:ft=objc:ts=8:et:sts=4:sw=4 +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/PropertyPane.m b/tikzit/src/linux/PropertyPane.m index 33ed29d..35910f7 100644 --- a/tikzit/src/linux/PropertyPane.m +++ b/tikzit/src/linux/PropertyPane.m @@ -16,6 +16,7 @@ */ #import "PropertyPane.h" +#import "PropertyListEditor.h" #import "GraphElementProperty.h" #import "gtkhelpers.h" diff --git a/tikzit/src/linux/StylesPane.h b/tikzit/src/linux/StylesPane.h new file mode 100644 index 0000000..c1a603d --- /dev/null +++ b/tikzit/src/linux/StylesPane.h @@ -0,0 +1,49 @@ +/* + * Copyright 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 EdgeStylesPalette; +@class NodeStylesPalette; +@class StyleManager; +@class TikzDocument; + +@interface StylesPane: NSObject { + NodeStylesPalette *nodeStyles; + EdgeStylesPalette *edgeStyles; + + GtkWidget *stylesPane; + + GtkExpander *nodeStylesExpander; + GtkExpander *edgeStylesExpander; +} + +@property (readonly) GtkWidget *widget; +@property (retain) TikzDocument *document; +@property (retain) StyleManager *styleManager; + +- (id) initWithManager:(StyleManager*)m; + +- (void) restoreUiStateFromConfig:(Configuration*)file group:(NSString*)group; +- (void) saveUiStateToConfig:(Configuration*)file group:(NSString*)group; + +@end + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker + diff --git a/tikzit/src/linux/StylesPane.m b/tikzit/src/linux/StylesPane.m new file mode 100644 index 0000000..0f6adef --- /dev/null +++ b/tikzit/src/linux/StylesPane.m @@ -0,0 +1,143 @@ +/* + * Copyright 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 "StylesPane.h" + +#import "Configuration.h" +#import "NodeStylesPalette.h" +#import "EdgeStylesPalette.h" + +@interface StylesPane (Private) +- (void) _addSplitter; +- (GtkExpander*) _addExpanderWithName:(const gchar*)name contents:(GtkWidget*)contents; +@end + +@implementation StylesPane + +@synthesize widget=stylesPane; + +- (id) init { + [self dealloc]; + self = nil; + return nil; +} + +- (id) initWithManager:(StyleManager*)m { + self = [super init]; + + if (self) { + nodeStyles = [[NodeStylesPalette alloc] initWithManager:m]; + edgeStyles = [[EdgeStylesPalette alloc] initWithManager:m]; + + stylesPane = gtk_vbox_new (FALSE, 0); + g_object_ref_sink (stylesPane); + + nodeStylesExpander = [self _addExpanderWithName:"Node styles" + contents:[nodeStyles widget]]; + g_object_ref_sink (nodeStylesExpander); + [self _addSplitter]; + + edgeStylesExpander = [self _addExpanderWithName:"Edge styles" + contents:[edgeStyles widget]]; + g_object_ref_sink (edgeStylesExpander); + [self _addSplitter]; + } + + return self; +} + +- (void) dealloc { + g_object_unref (stylesPane); + + [nodeStyles release]; + [edgeStyles release]; + + [super dealloc]; +} + +- (TikzDocument*) document { + return [nodeStyles document]; +} + +- (void) setDocument:(TikzDocument*)doc { + [nodeStyles setDocument:doc]; + [edgeStyles setDocument:doc]; +} + +- (StyleManager*) styleManager { + return [nodeStyles styleManager]; +} + +- (void) setStyleManager:(StyleManager*)m { + [nodeStyles setStyleManager:m]; + [edgeStyles setStyleManager:m]; +} + +- (void) restoreUiStateFromConfig:(Configuration*)file group:(NSString*)group { + gtk_expander_set_expanded (nodeStylesExpander, + [file booleanEntry:@"node-styles-expanded" + inGroup:group + withDefault:YES]); + gtk_expander_set_expanded (edgeStylesExpander, + [file booleanEntry:@"edge-styles-expanded" + inGroup:group + withDefault:NO]); +} + +- (void) saveUiStateToConfig:(Configuration*)file group:(NSString*)group { + [file setBooleanEntry:@"node-styles-expanded" + inGroup:group + value:gtk_expander_get_expanded (nodeStylesExpander)]; + [file setBooleanEntry:@"edge-styles-expanded" + inGroup:group + value:gtk_expander_get_expanded (edgeStylesExpander)]; +} + +@end + +// }}} +// {{{ Private + +@implementation StylesPane (Private) +- (void) _addSplitter { + GtkWidget *split = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX (stylesPane), + split, + FALSE, // expand + FALSE, // fill + 0); // padding + gtk_widget_show (split); +} + +- (GtkExpander*) _addExpanderWithName:(const gchar*)name contents:(GtkWidget*)contents { + GtkWidget *exp = gtk_expander_new (name); + gtk_box_pack_start (GTK_BOX (stylesPane), + exp, + FALSE, // expand + TRUE, // fill + 0); // padding + gtk_widget_show (exp); + gtk_container_set_border_width (GTK_CONTAINER (contents), 6); + gtk_container_add (GTK_CONTAINER (exp), contents); + gtk_widget_show (contents); + return GTK_EXPANDER (exp); +} +@end + +// }}} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker diff --git a/tikzit/src/linux/TikzDocument.h b/tikzit/src/linux/TikzDocument.h index 5ab5f30..11f754b 100644 --- a/tikzit/src/linux/TikzDocument.h +++ b/tikzit/src/linux/TikzDocument.h @@ -35,6 +35,8 @@ NSString *path; NSSet *nodesetBeingModified; BasicMapTable *nodesetBeingModifiedOldCopy; + NSSet *edgesetBeingModified; + BasicMapTable *edgesetBeingModifiedOldCopy; NSPoint currentNodeShift; Node *nodeBeingModified; Node *nodeBeingModifiedOldCopy; @@ -110,6 +112,11 @@ - (void) endModifyEdge; - (void) cancelModifyEdge; +- (void) startModifyEdges:(NSSet*)edges; +- (void) modifyEdgesCheckPoint; +- (void) endModifyEdges; +- (void) cancelModifyEdges; + - (void) startChangeBoundingBox; - (void) changeBoundingBoxCheckPoint; - (void) endChangeBoundingBox; diff --git a/tikzit/src/linux/TikzDocument.m b/tikzit/src/linux/TikzDocument.m index 43001cc..5556654 100644 --- a/tikzit/src/linux/TikzDocument.m +++ b/tikzit/src/linux/TikzDocument.m @@ -523,6 +523,40 @@ - (void) endModifyEdge { [self _finishModifyEdgeCancelled:NO]; } - (void) cancelModifyEdge { [self _finishModifyEdgeCancelled:YES]; } +- (void) startModifyEdges:(NSSet*)edges { + if (edgesetBeingModified != nil) { + [NSException raise:@"NSInternalInconsistencyException" format:@"Already modifying an edge set"]; + } + + edgesetBeingModified = [edges copy]; + edgesetBeingModifiedOldCopy = [[Graph edgeTableForEdges:edges] retain]; +} + +- (void) modifyEdgesCheckPoint { + [self regenerateTikz]; + GraphChange *change = [GraphChange propertyChangeOfEdgesFromOldCopies:edgesetBeingModifiedOldCopy + toNewCopies:[Graph edgeTableForEdges:edgesetBeingModified]]; + [self postIncompleteGraphChange:change]; +} + +- (void) _finishModifyEdgesCancelled:(BOOL)cancelled { + if (edgesetBeingModified == nil) { + [NSException raise:@"NSInternalInconsistencyException" format:@"Not modifying an edge"]; + } + + GraphChange *change = [GraphChange propertyChangeOfEdgesFromOldCopies:edgesetBeingModifiedOldCopy + toNewCopies:[Graph edgeTableForEdges:edgesetBeingModified]]; + [self _finishModifySequence:change withName:@"Modify edges" cancelled:cancelled]; + + [edgesetBeingModified release]; + edgesetBeingModified = nil; + [edgesetBeingModifiedOldCopy release]; + edgesetBeingModifiedOldCopy = nil; +} + +- (void) endModifyEdges { [self _finishModifyEdgesCancelled:NO]; } +- (void) cancelModifyEdges { [self _finishModifyEdgesCancelled:YES]; } + - (void) startChangeBoundingBox { oldGraphBounds = [graph boundingBox]; } -- cgit v1.2.3