From 2ed61cfb3ad3d404b9a44bbb3f4c8083b469ae22 Mon Sep 17 00:00:00 2001 From: randomguy3 Date: Fri, 6 Jan 2012 13:44:40 +0000 Subject: Move everything into trunk. Also add branches and tags directories. git-svn-id: https://tikzit.svn.sourceforge.net/svnroot/tikzit/trunk@348 7c02a99a-9b00-45e3-bf44-6f3dd7fddb64 --- src/linux/PropertyListEditor.m | 417 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 src/linux/PropertyListEditor.m (limited to 'src/linux/PropertyListEditor.m') diff --git a/src/linux/PropertyListEditor.m b/src/linux/PropertyListEditor.m new file mode 100644 index 0000000..cf04726 --- /dev/null +++ b/src/linux/PropertyListEditor.m @@ -0,0 +1,417 @@ +/* + * Copyright 2011 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "PropertyListEditor.h" + +// {{{ Constants + +enum { + PLM_NAME_COL = 0, + PLM_VALUE_COL, + PLM_IS_PROPERTY_COL, + PLM_PROPERTY_COL, + PLM_N_COLS +}; + +// }}} +// {{{ Internal interfaces +// {{{ Signals + +static void value_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + PropertyListEditor *editor); +static void name_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + PropertyListEditor *editor); +static void add_prop_clicked_cb (GtkButton *button, + PropertyListEditor *editor); +static void add_atom_clicked_cb (GtkButton *button, + PropertyListEditor *editor); +static void remove_clicked_cb (GtkButton *button, + PropertyListEditor *editor); + +// }}} +// {{{ Private + +@interface PropertyListEditor (Private) +- (void) updatePath:(gchar*)path withValue:(NSString*)newText; +- (void) updatePath:(gchar*)path withName:(NSString*)newText; +- (void) addProperty; +- (void) addAtom; +- (void) removeSelected; +@end + +// }}} +// }}} +// {{{ API + +@implementation PropertyListEditor + +- (id) init { + self = [super init]; + + if (self) { + list = gtk_list_store_new (PLM_N_COLS, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_POINTER); + view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list)); + GtkWidget *scrolledview = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledview), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (scrolledview), view); + gtk_widget_set_size_request (view, -1, 150); + data = nil; + delegate = nil; + + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), + "editable", TRUE, + NULL); + column = gtk_tree_view_column_new_with_attributes ("Key/Atom", + renderer, + "text", PLM_NAME_COL, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + g_signal_connect (G_OBJECT (renderer), + "edited", + G_CALLBACK (name_edited_cb), + self); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Value", + renderer, + "text", PLM_VALUE_COL, + "editable", PLM_IS_PROPERTY_COL, + "sensitive", PLM_IS_PROPERTY_COL, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + g_signal_connect (G_OBJECT (renderer), + "edited", + G_CALLBACK (value_edited_cb), + self); + + widget = gtk_vbox_new (FALSE, 0); + g_object_ref_sink (G_OBJECT (widget)); + gtk_container_add (GTK_CONTAINER (widget), scrolledview); + + GtkBox *buttonBox = GTK_BOX (gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start (GTK_BOX (widget), GTK_WIDGET (buttonBox), FALSE, FALSE, 0); + + GtkWidget *addPropButton = gtk_button_new (); + //gtk_widget_set_size_request (addPropButton, 27, 27); + gtk_widget_set_tooltip_text (addPropButton, "Add property"); + GtkWidget *addPropContents = gtk_hbox_new(FALSE, 0); + GtkWidget *addPropIcon = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (addPropContents), addPropIcon); + gtk_container_add (GTK_CONTAINER (addPropContents), gtk_label_new ("P")); + gtk_container_add (GTK_CONTAINER (addPropButton), addPropContents); + gtk_box_pack_start (buttonBox, addPropButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (addPropButton), + "clicked", + G_CALLBACK (add_prop_clicked_cb), + self); + + GtkWidget *addAtomButton = gtk_button_new (); + //gtk_widget_set_size_request (addAtomButton, 27, 27); + gtk_widget_set_tooltip_text (addAtomButton, "Add atom"); + GtkWidget *addAtomContents = gtk_hbox_new(FALSE, 0); + GtkWidget *addAtomIcon = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (addAtomContents), addAtomIcon); + gtk_container_add (GTK_CONTAINER (addAtomContents), gtk_label_new ("A")); + gtk_container_add (GTK_CONTAINER (addAtomButton), addAtomContents); + gtk_box_pack_start (buttonBox, addAtomButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (addAtomButton), + "clicked", + G_CALLBACK (add_atom_clicked_cb), + self); + + GtkWidget *removeButton = gtk_button_new (); + //gtk_widget_set_size_request (removeButton, 27, 27); + gtk_widget_set_tooltip_text (removeButton, "Remove selected"); + GtkWidget *removeIcon = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (removeButton), removeIcon); + gtk_box_pack_start (buttonBox, removeButton, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (removeButton), + "clicked", + G_CALLBACK (remove_clicked_cb), + self); + + gtk_widget_show_all (GTK_WIDGET (buttonBox)); + gtk_widget_show_all (scrolledview); + } + + return self; +} + +- (void) clearStore { + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list), &iter)) { + do { + void *prop; + gtk_tree_model_get (GTK_TREE_MODEL (list), &iter, + PLM_PROPERTY_COL, &prop, + -1); + [(id)prop release]; + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (list), &iter)); + gtk_list_store_clear (list); + } +} + +- (void) reloadProperties { + [self clearStore]; + int pos = 0; + for (GraphElementProperty *p in data) { + GtkTreeIter iter; + [p retain]; + gtk_list_store_insert_with_values (list, &iter, pos, + PLM_NAME_COL, [[p key] UTF8String], + PLM_VALUE_COL, [[p value] UTF8String], + PLM_IS_PROPERTY_COL, ![p isAtom], + PLM_PROPERTY_COL, (void *)p, + -1); + ++pos; + } +} + +- (GtkWidget*) widget { return widget; } +- (GraphElementData*) data { return data; } +- (void) setData:(GraphElementData*)d { + [d retain]; + [data release]; + data = d; + [self reloadProperties]; +} + +- (NSObject*) delegate { + return delegate; +} + +- (void) setDelegate:(NSObject*)d { + id oldDelegate = delegate; + delegate = [d retain]; + [oldDelegate release]; +} + +- (void) dealloc { + [self clearStore]; + [data release]; + g_object_unref (list); + g_object_unref (widget); + [super dealloc]; +} + +@end + +// }}} +// {{{ Private + +@implementation PropertyListEditor (Private) +- (void) updatePath:(gchar*)pathStr withValue:(NSString*)newText { + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string (pathStr); + + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (list), &iter, path)) { + gtk_tree_path_free (path); + return; + } + + void *propPtr; + gtk_tree_model_get (GTK_TREE_MODEL (list), &iter, + PLM_PROPERTY_COL, &propPtr, + -1); + GraphElementProperty *prop = (GraphElementProperty*)propPtr; + + if (![prop isAtom]) { + if (![delegate respondsToSelector:@selector(startEdit)] || [delegate startEdit]) { + [prop setValue:newText]; + gtk_list_store_set (list, &iter, + PLM_VALUE_COL, [newText UTF8String], + -1); + [delegate endEdit]; + } + } + + gtk_tree_path_free (path); +} + +- (void) updatePath:(gchar*)pathStr withName:(NSString*)newText { + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string (pathStr); + + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (list), &iter, path)) { + gtk_tree_path_free (path); + return; + } + + void *propPtr; + gtk_tree_model_get (GTK_TREE_MODEL (list), &iter, + PLM_PROPERTY_COL, &propPtr, + -1); + GraphElementProperty *prop = (GraphElementProperty*)propPtr; + + if (![delegate respondsToSelector:@selector(startEdit)] || [delegate startEdit]) { + if ([newText isEqualToString:@""]) { + [data removeObjectIdenticalTo:prop]; + gtk_list_store_remove (list, &iter); + [prop release]; + } else { + [prop setKey:newText]; + gtk_list_store_set (list, &iter, + PLM_NAME_COL, [newText UTF8String], + -1); + } + [delegate endEdit]; + } + + gtk_tree_path_free (path); +} + +- (void) addProperty { + GtkTreeIter iter; + GraphElementProperty *p = [[GraphElementProperty alloc] initWithPropertyValue:@"" forKey:@"new property"]; + if (![delegate respondsToSelector:@selector(startEdit)] || [delegate startEdit]) { + [data addObject:p]; + gint pos = [data count] - 1; + gtk_list_store_insert_with_values (list, &iter, pos, + PLM_NAME_COL, "new property", + PLM_VALUE_COL, "", + PLM_IS_PROPERTY_COL, TRUE, + PLM_PROPERTY_COL, (void *)p, + -1); + [delegate endEdit]; + } else { + [p release]; + } +} + +- (void) addAtom { + GtkTreeIter iter; + GraphElementProperty *p = [[GraphElementProperty alloc] initWithAtomName:@"new atom"]; + if (![delegate respondsToSelector:@selector(startEdit)] || [delegate startEdit]) { + [data addObject:p]; + gint pos = [data count] - 1; + gtk_list_store_insert_with_values (list, &iter, pos, + PLM_NAME_COL, "new atom", + PLM_VALUE_COL, [[p value] UTF8String], + PLM_IS_PROPERTY_COL, FALSE, + PLM_PROPERTY_COL, (void *)p, + -1); + [delegate endEdit]; + } else { + [p release]; + } +} + +- (void) removeSelected { + GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + GList *selPaths = gtk_tree_selection_get_selected_rows (selection, NULL); + GList *selIters = NULL; + + // Convert to iters, as GtkListStore has persistent iters + GList *curr = selPaths; + while (curr != NULL) { + GtkTreeIter iter; + gtk_tree_model_get_iter (GTK_TREE_MODEL (list), + &iter, + (GtkTreePath*)curr->data); + selIters = g_list_prepend (selIters, gtk_tree_iter_copy (&iter)); + curr = g_list_next (curr); + } + + // remove all iters + curr = selIters; + while (curr != NULL) { + GtkTreeIter *iter = (GtkTreeIter*)curr->data; + void *propPtr; + gtk_tree_model_get (GTK_TREE_MODEL (list), iter, + PLM_PROPERTY_COL, &propPtr, + -1); + GraphElementProperty *prop = (GraphElementProperty*)propPtr; + if (![delegate respondsToSelector:@selector(startEdit)] || [delegate startEdit]) { + [data removeObjectIdenticalTo:prop]; + gtk_list_store_remove (list, iter); + [prop release]; + [delegate endEdit]; + } + curr = g_list_next (curr); + } + + g_list_foreach (selIters, (GFunc) gtk_tree_iter_free, NULL); + g_list_free (selIters); + g_list_foreach (selPaths, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selPaths); +} +@end + +// }}} +// {{{ GTK+ callbacks + +static void value_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + PropertyListEditor *editor) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor updatePath:path withValue:[NSString stringWithUTF8String:new_text]]; + [pool drain]; +} + +static void name_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + PropertyListEditor *editor) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor updatePath:path withName:[NSString stringWithUTF8String:new_text]]; + [pool drain]; +} + +static void add_prop_clicked_cb (GtkButton *button, + PropertyListEditor *editor) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor addProperty]; + [pool drain]; +} + +static void add_atom_clicked_cb (GtkButton *button, + PropertyListEditor *editor) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor addAtom]; + [pool drain]; +} + +static void remove_clicked_cb (GtkButton *button, + PropertyListEditor *editor) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [editor removeSelected]; + [pool drain]; +} + +// }}} + +// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker -- cgit v1.2.3