summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Merry <alex.merry@cs.ox.ac.uk>2013-02-04 18:08:38 +0000
committerAlex Merry <alex.merry@cs.ox.ac.uk>2013-02-04 18:08:38 +0000
commitdc720cc5d5e3f5b2f3d8119947a9dd8c69f4b2df (patch)
tree7b3eeeaca920b37f45d3c762ea6dc6c625760780
parent0f2452356ae718b73e9467e388092c8af6752a8f (diff)
GTK: prevent the user from creating invalid tikz
The free-form entry fields (graph element properties and node labels) are a potential source of invalid tikz code. Since we quote any dodgy-looking text with { and }, we just need to make sure there are no unmatched curly braces entered in those fields. This will turn the entry widgets red when there are unmatched braces, and refuse to make use of any such values.
-rw-r--r--tikzit/src/gtk/PropertiesPane.m28
-rw-r--r--tikzit/src/gtk/PropertyListEditor.m52
-rw-r--r--tikzit/src/gtk/TZFoundation.h1
-rw-r--r--tikzit/src/gtk/Window.m5
-rw-r--r--tikzit/src/gtk/gtkhelpers.h3
-rw-r--r--tikzit/src/gtk/gtkhelpers.m9
6 files changed, 86 insertions, 12 deletions
diff --git a/tikzit/src/gtk/PropertiesPane.m b/tikzit/src/gtk/PropertiesPane.m
index 990304e..36dd079 100644
--- a/tikzit/src/gtk/PropertiesPane.m
+++ b/tikzit/src/gtk/PropertiesPane.m
@@ -337,10 +337,14 @@ static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane)
return;
}
- Node *node = [sel anyObject];
- [document startModifyNode:node];
- [node setLabel:newValue];
- [document endModifyNode];
+ if ([newValue isValidTikz]) {
+ Node *node = [sel anyObject];
+ [document startModifyNode:node];
+ [node setLabel:newValue];
+ [document endModifyNode];
+ } else {
+ widget_set_error (GTK_WIDGET (nodeLabelEntry));
+ }
}
- (void) edgeNodeLabelEdited:(NSString*)newValue {
@@ -359,9 +363,13 @@ static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane)
return;
}
- [document startModifyEdge:edge];
- [[edge edgeNode] setLabel:newValue];
- [document endModifyEdge];
+ if ([newValue isValidTikz]) {
+ [document startModifyEdge:edge];
+ [[edge edgeNode] setLabel:newValue];
+ [document endModifyEdge];
+ } else {
+ widget_set_error (GTK_WIDGET (edgeNodeLabelEntry));
+ }
}
- (void) edgeNodeToggled:(BOOL)newValue {
@@ -410,6 +418,7 @@ static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane)
[nodePropDelegate setNode:n];
[nodeProps setData:[n data]];
gtk_entry_set_text (nodeLabelEntry, [[n label] UTF8String]);
+ widget_clear_error (GTK_WIDGET (nodeLabelEntry));
[self _setDisplayedWidget:nodePropsWidget];
editGraphProps = NO;
} else {
@@ -422,16 +431,17 @@ static void edge_node_toggled_cb (GtkToggleButton *widget, PropertiesPane *pane)
Edge *e = [edgeSel anyObject];
[edgePropDelegate setEdge:e];
[edgeProps setData:[e data]];
+ widget_clear_error (GTK_WIDGET (edgeNodeLabelEntry));
if ([e hasEdgeNode]) {
gtk_toggle_button_set_active (edgeNodeToggle, TRUE);
gtk_widget_show (edgeNodePropsWidget);
- gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), [[[e edgeNode] label] UTF8String]);
+ gtk_entry_set_text (edgeNodeLabelEntry, [[[e edgeNode] label] UTF8String]);
[edgeNodeProps setData:[[e edgeNode] data]];
gtk_widget_set_sensitive (edgeNodePropsWidget, TRUE);
} else {
gtk_toggle_button_set_active (edgeNodeToggle, FALSE);
gtk_widget_hide (edgeNodePropsWidget);
- gtk_entry_set_text (GTK_ENTRY (edgeNodeLabelEntry), "");
+ gtk_entry_set_text (edgeNodeLabelEntry, "");
[edgeNodeProps setData:nil];
gtk_widget_set_sensitive (edgeNodePropsWidget, FALSE);
}
diff --git a/tikzit/src/gtk/PropertyListEditor.m b/tikzit/src/gtk/PropertyListEditor.m
index ba909da..72b7441 100644
--- a/tikzit/src/gtk/PropertyListEditor.m
+++ b/tikzit/src/gtk/PropertyListEditor.m
@@ -16,6 +16,7 @@
*/
#import "PropertyListEditor.h"
+#import "gtkhelpers.h"
// {{{ Constants
@@ -45,6 +46,12 @@ static void add_atom_clicked_cb (GtkButton *button,
PropertyListEditor *editor);
static void remove_clicked_cb (GtkButton *button,
PropertyListEditor *editor);
+static void text_editing_started (GtkCellRenderer *cell,
+ GtkCellEditable *editable,
+ const gchar *path,
+ PropertyListEditor *editor);
+static void text_changed_cb (GtkEditable *editable,
+ PropertyListEditor *pane);
// }}}
// {{{ Private
@@ -95,6 +102,10 @@ static void remove_clicked_cb (GtkButton *button,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
g_signal_connect (G_OBJECT (renderer),
+ "editing-started",
+ G_CALLBACK (text_editing_started),
+ self);
+ g_signal_connect (G_OBJECT (renderer),
"edited",
G_CALLBACK (name_edited_cb),
self);
@@ -237,6 +248,9 @@ static void remove_clicked_cb (GtkButton *button,
@implementation PropertyListEditor (Private)
- (void) updatePath:(gchar*)pathStr withValue:(NSString*)newText {
+ if (![newText isValidTikz])
+ return;
+
GtkTreeIter iter;
GtkTreePath *path = gtk_tree_path_new_from_string (pathStr);
@@ -265,6 +279,9 @@ static void remove_clicked_cb (GtkButton *button,
}
- (void) updatePath:(gchar*)pathStr withName:(NSString*)newText {
+ if (![newText isValidTikz])
+ return;
+
GtkTreeIter iter;
GtkTreePath *path = gtk_tree_path_new_from_string (pathStr);
@@ -420,6 +437,41 @@ static void remove_clicked_cb (GtkButton *button,
[pool drain];
}
+static void text_editing_started (GtkCellRenderer *cell,
+ GtkCellEditable *editable,
+ const gchar *path,
+ PropertyListEditor *editor)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (GTK_IS_EDITABLE (editable) && GTK_IS_WIDGET (editable)) {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (editable),
+ G_CALLBACK (text_changed_cb),
+ editor);
+ widget_clear_error (GTK_WIDGET (editable));
+ g_signal_connect (G_OBJECT (editable),
+ "changed",
+ G_CALLBACK (text_changed_cb),
+ editor);
+ }
+
+ [pool drain];
+}
+
+static void text_changed_cb (GtkEditable *editable, PropertyListEditor *pane)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSString *newValue = gtk_editable_get_string (editable, 0, -1);
+ if (![newValue isValidTikz]) {
+ widget_set_error (GTK_WIDGET (editable));
+ } else {
+ widget_clear_error (GTK_WIDGET (editable));
+ }
+
+ [pool drain];
+}
+
// }}}
// vim:ft=objc:ts=8:et:sts=4:sw=4:foldmethod=marker
diff --git a/tikzit/src/gtk/TZFoundation.h b/tikzit/src/gtk/TZFoundation.h
index 6f42700..f275004 100644
--- a/tikzit/src/gtk/TZFoundation.h
+++ b/tikzit/src/gtk/TZFoundation.h
@@ -24,5 +24,6 @@
#import "NSFileManager+Utils.h"
#import "NSString+Glib.h"
#import "NSString+LatexConstants.h"
+#import "NSString+Tikz.h"
// vim:ft=objc:ts=8:et:sts=4:sw=4
diff --git a/tikzit/src/gtk/Window.m b/tikzit/src/gtk/Window.m
index 15049ea..66ffc27 100644
--- a/tikzit/src/gtk/Window.m
+++ b/tikzit/src/gtk/Window.m
@@ -685,11 +685,10 @@ static void update_paste_action (GtkClipboard *clipboard, GdkEvent *event, GtkAc
- (void) _setHasParseError:(BOOL)hasError {
if (hasError && !hasParseError) {
gtk_statusbar_push (statusBar, 1, "Parse error");
- GdkColor color = {0, 65535, 61184, 61184};
- gtk_widget_modify_base (tikzPane, GTK_STATE_NORMAL, &color);
+ widget_set_error (tikzPane);
} else if (!hasError && hasParseError) {
gtk_statusbar_pop (statusBar, 1);
- gtk_widget_modify_base (tikzPane, GTK_STATE_NORMAL, NULL);
+ widget_clear_error (tikzPane);
}
hasParseError = hasError;
}
diff --git a/tikzit/src/gtk/gtkhelpers.h b/tikzit/src/gtk/gtkhelpers.h
index a28b127..abc2f4f 100644
--- a/tikzit/src/gtk/gtkhelpers.h
+++ b/tikzit/src/gtk/gtkhelpers.h
@@ -50,4 +50,7 @@ void tz_restore_window (GtkWindow *window, gint x, gint y, gint w, gint h);
void label_set_bold (GtkLabel *label);
+void widget_set_error (GtkWidget *widget);
+void widget_clear_error (GtkWidget *widget);
+
// vim:ft=objc:sts=2:sw=2:et
diff --git a/tikzit/src/gtk/gtkhelpers.m b/tikzit/src/gtk/gtkhelpers.m
index c37077b..b3a3cf7 100644
--- a/tikzit/src/gtk/gtkhelpers.m
+++ b/tikzit/src/gtk/gtkhelpers.m
@@ -234,4 +234,13 @@ void label_set_bold (GtkLabel *label) {
pango_attr_list_unref (attrs);
}
+void widget_set_error (GtkWidget *widget) {
+ GdkColor color = {0, 65535, 61184, 61184};
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, &color);
+}
+
+void widget_clear_error (GtkWidget *widget) {
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, NULL);
+}
+
// vim:ft=objc:ts=8:et:sts=4:sw=4