diff options
Diffstat (limited to 'tikzit-old/src/gtk/EdgeStyleEditor.m')
-rw-r--r-- | tikzit-old/src/gtk/EdgeStyleEditor.m | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/tikzit-old/src/gtk/EdgeStyleEditor.m b/tikzit-old/src/gtk/EdgeStyleEditor.m new file mode 100644 index 0000000..c7ca8bd --- /dev/null +++ b/tikzit-old/src/gtk/EdgeStyleEditor.m @@ -0,0 +1,499 @@ +/* + * Copyright 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 "EdgeStyleEditor.h" + +#import "EdgeStyle.h" +#import "EdgeStyle+Gtk.h" +#import "Shape.h" + +#include <gdk-pixbuf/gdk-pixdata.h> + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-sign" +#import "edgedecdata.m" +#pragma GCC diagnostic pop + +// {{{ Data Types +enum { + DEC_NAME_COL = 0, + DEC_PREVIEW_COL, + DEC_VALUE_COL, + DEC_N_COLS +}; + +struct dec_info { + const gchar *name; + const GdkPixdata *pixdata; + int value; +}; +static struct dec_info ed_entries[] = { + { "None", &ED_none_pixdata, ED_None }, + { "Arrow", &ED_arrow_pixdata, ED_Arrow }, + { "Tick", &ED_tick_pixdata, ED_Tick } +}; +static guint n_ed_entries = G_N_ELEMENTS (ed_entries); +static struct dec_info ah_head_entries[] = { + { "None", &AH_none_pixdata, AH_None }, + { "Plain", &AH_plain_head_pixdata, AH_Plain }, + { "Latex", &AH_latex_head_pixdata, AH_Latex } +}; +static guint n_ah_head_entries = G_N_ELEMENTS (ah_head_entries); +static struct dec_info ah_tail_entries[] = { + { "None", &AH_none_pixdata, AH_None }, + { "Plain", &AH_plain_tail_pixdata, AH_Plain }, + { "Latex", &AH_latex_tail_pixdata, AH_Latex } +}; +static guint n_ah_tail_entries = G_N_ELEMENTS (ah_tail_entries); + +static const guint row_count = 6; + +// }}} +// {{{ 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 head_arrow_combo_changed_cb (GtkComboBox *widget, EdgeStyleEditor *editor); +static void tail_arrow_combo_changed_cb (GtkComboBox *widget, EdgeStyleEditor *editor); +static void thickness_adjustment_changed_cb (GtkAdjustment *widget, EdgeStyleEditor *editor); +static void color_changed_cb (GtkColorButton *widget, EdgeStyleEditor *editor); +static void make_color_safe_button_clicked_cb (GtkButton *widget, EdgeStyleEditor *editor); +// }}} +// {{{ Notifications + +@interface EdgeStyleEditor (Notifications) +- (void) nameChangedTo:(NSString*)value; +- (void) edgeDecorationChangedTo:(EdgeDectorationStyle)value; +- (void) headArrowChangedTo:(ArrowHeadStyle)value; +- (void) tailArrowChangedTo:(ArrowHeadStyle)value; +- (void) thicknessChangedTo:(double)value; +- (void) makeColorTexSafe; +- (void) colorChangedTo:(GdkColor)value; +@end + +// }}} +// {{{ Private + +@interface EdgeStyleEditor (Private) +- (void) load:(guint)count decorationStylesFrom:(struct dec_info*)info into:(GtkListStore*)list; +- (void) clearDecCombo:(GtkComboBox*)combo; +- (void) setDecCombo:(GtkComboBox*)combo toValue:(int)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 +} + +- (GtkComboBox*) _createDecComboWithEntries:(struct dec_info*)entries count:(guint)n { + GtkListStore *store = gtk_list_store_new (DEC_N_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT); + [self load:n decorationStylesFrom:entries into:store]; + + GtkComboBox *combo = 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 (combo), + cellRend, + TRUE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cellRend, "pixbuf", DEC_PREVIEW_COL); + g_object_ref_sink (combo); + + return combo; +} + +- (GtkWidget*) _createMakeColorTexSafeButton { + 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 = @"The colour is not a predefined TeX colour.\nClick here to choose the nearest TeX-safe colour."; + 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); + + + /** + * Edge decoration style + */ + decorationCombo = [self _createDecComboWithEntries:ed_entries count:n_ed_entries]; + [self _addWidget:GTK_WIDGET (decorationCombo) + withLabel:"Decoration" + atRow:1]; + g_signal_connect (G_OBJECT (decorationCombo), + "changed", + G_CALLBACK (decoration_combo_changed_cb), + self); + + + /** + * Head arrow style + */ + headArrowCombo = [self _createDecComboWithEntries:ah_head_entries count:n_ah_head_entries]; + [self _addWidget:GTK_WIDGET (headArrowCombo) + withLabel:"Arrow head" + atRow:2]; + g_signal_connect (G_OBJECT (headArrowCombo), + "changed", + G_CALLBACK (head_arrow_combo_changed_cb), + self); + + + /** + * Tail arrow style + */ + tailArrowCombo = [self _createDecComboWithEntries:ah_tail_entries count:n_ah_tail_entries]; + [self _addWidget:GTK_WIDGET (tailArrowCombo) + withLabel:"Arrow tail" + atRow:3]; + g_signal_connect (G_OBJECT (tailArrowCombo), + "changed", + G_CALLBACK (tail_arrow_combo_changed_cb), + self); + + + /** + * Colour + */ + GtkWidget *colorBox = gtk_hbox_new (FALSE, 0); + [self _addWidget:colorBox + withLabel:"Colour" + atRow:4]; + colorButton = GTK_COLOR_BUTTON (gtk_color_button_new ()); + g_object_ref_sink (colorButton); + gtk_widget_show (GTK_WIDGET (colorButton)); + gtk_box_pack_start (GTK_BOX (colorBox), GTK_WIDGET (colorButton), + FALSE, FALSE, 0); + makeColorTexSafeButton = [self _createMakeColorTexSafeButton]; + g_object_ref_sink (makeColorTexSafeButton); + gtk_box_pack_start (GTK_BOX (colorBox), makeColorTexSafeButton, + FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (colorButton), + "color-set", + G_CALLBACK (color_changed_cb), + self); + g_signal_connect (G_OBJECT (makeColorTexSafeButton), + "clicked", + G_CALLBACK (make_color_safe_button_clicked_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:5]; + 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 (colorButton); + g_object_unref (makeColorTexSafeButton); + 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 setDecCombo:decorationCombo toValue:[style decorationStyle]]; + [self setDecCombo:headArrowCombo toValue:[style headStyle]]; + [self setDecCombo:tailArrowCombo toValue:[style tailStyle]]; + + GdkColor c = [style color]; + gtk_color_button_set_color(colorButton, &c); + gtk_widget_set_visible (makeColorTexSafeButton, ([[style colorRGB] name] == nil)); + + gtk_adjustment_set_value(thicknessAdj, [style thickness]); + } else { + gtk_entry_set_text(nameEdit, ""); + [self clearDecCombo:decorationCombo]; + [self clearDecCombo:headArrowCombo]; + [self clearDecCombo:tailArrowCombo]; + gtk_widget_set_visible (makeColorTexSafeButton, FALSE); + 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); +} + +- (void) selectNameField { + gtk_widget_grab_focus (GTK_WIDGET (nameEdit)); + gtk_editable_select_region (GTK_EDITABLE (nameEdit), 0, -1); +} + +@end + +// }}} +// {{{ Notifications + +@implementation EdgeStyleEditor (Notifications) +- (void) nameChangedTo:(NSString*)value { + [style setName:value]; +} + +- (void) edgeDecorationChangedTo:(EdgeDectorationStyle)value { + [style setDecorationStyle:value]; +} + +- (void) headArrowChangedTo:(ArrowHeadStyle)value { + [style setHeadStyle:value]; +} + +- (void) tailArrowChangedTo:(ArrowHeadStyle)value { + [style setTailStyle:value]; +} + +- (void) thicknessChangedTo:(double)value { + [style setThickness:(float)value]; +} + +- (void) colorChangedTo:(GdkColor)value { + [style setColor:value]; + gtk_widget_set_visible (makeColorTexSafeButton, + [[style colorRGB] name] == nil); +} + +- (void) makeColorTexSafe { + if (style != nil) { + [[style colorRGB] setToClosestHashed]; + GdkColor color = [style color]; + gtk_color_button_set_color(colorButton, &color); + gtk_widget_set_visible (makeColorTexSafeButton, FALSE); + } +} +@end + +// }}} +// {{{ Private + +@implementation EdgeStyleEditor (Private) +- (BOOL) signalsBlocked { return blockSignals; } + +- (void) load:(guint)count decorationStylesFrom:(struct dec_info*)info into:(GtkListStore*)list { + GtkTreeIter iter; + + for (guint i = 0; i < count; ++i) { + GdkPixbuf *buf = gdk_pixbuf_from_pixdata (info[i].pixdata, FALSE, NULL); + gtk_list_store_append (list, &iter); + gtk_list_store_set (list, &iter, + DEC_NAME_COL, info[i].name, + DEC_PREVIEW_COL, buf, + DEC_VALUE_COL, info[i].value, + -1); + g_object_unref (buf); + } +} + +- (void) clearDecCombo:(GtkComboBox*)combo { + gtk_combo_box_set_active (combo, -1); +} + +- (void) setDecCombo:(GtkComboBox*)combo toValue:(int)value { + GtkTreeModel *model = gtk_combo_box_get_model (combo); + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + int rowValue; + gtk_tree_model_get (model, &iter, DEC_VALUE_COL, &rowValue, -1); + if (rowValue == value) { + gtk_combo_box_set_active_iter (combo, &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, DEC_VALUE_COL, &dec, -1); + [editor edgeDecorationChangedTo:dec]; + + [pool drain]; +} + +static void head_arrow_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); + ArrowHeadStyle dec = AH_None; + gtk_tree_model_get (gtk_combo_box_get_model (widget), &iter, DEC_VALUE_COL, &dec, -1); + [editor headArrowChangedTo:dec]; + + [pool drain]; +} + +static void tail_arrow_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); + ArrowHeadStyle dec = AH_None; + gtk_tree_model_get (gtk_combo_box_get_model (widget), &iter, DEC_VALUE_COL, &dec, -1); + [editor tailArrowChangedTo: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]; +} + +static void color_changed_cb (GtkColorButton *widget, EdgeStyleEditor *editor) { + if ([editor signalsBlocked]) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + GdkColor color; + gtk_color_button_get_color (widget, &color); + [editor colorChangedTo:color]; + + [pool drain]; +} + +static void make_color_safe_button_clicked_cb (GtkButton *widget, EdgeStyleEditor *editor) { + if ([editor signalsBlocked]) + return; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor makeColorTexSafe]; + [pool drain]; +} + +// }}} + +// vim:ft=objc:ts=4:et:sts=4:sw=4:foldmethod=marker |