From: Paolo Marinelli Date: Mon, 27 Jan 2003 16:34:49 +0000 (+0000) Subject: Added some controls concerning the graphical deleting. X-Git-Tag: V_0_0_4_1~87 X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=commitdiff_plain;h=6bb809fdd7a94a55031dbb50f5510539aae13b28;p=helm.git Added some controls concerning the graphical deleting. Now, it's possible to delete a macro which accepts (delimited or not delimited) arguments. To meet this goal, the following source files have been modified: src/TNode.* added a new public method: void TNode::replace(const TNode& first, TNode& last) This method is used to replace a node with the nodes between first (included) and last (not included). src/TPushParser.* Some code lines have been added to handle the graphical deleting of macro which accepts arguments. Added new private method: void TPushParser::rgreplace_futher(void) This method is used in TPushParser::gdelete_prev() and TPushParser::do_gdelete() methods. This method replaces a group with id having the cursor as unic child, with the cursor. Then, it repeats the control. dictionary.xml a new entry is avaible to test the deleting of a macro which is "leftOpen". --- diff --git a/helm/DEVEL/mathml_editor/dictionary.xml b/helm/DEVEL/mathml_editor/dictionary.xml index 664100c62..023bcdbe1 100644 --- a/helm/DEVEL/mathml_editor/dictionary.xml +++ b/helm/DEVEL/mathml_editor/dictionary.xml @@ -347,4 +347,7 @@ + + + diff --git a/helm/DEVEL/mathml_editor/src/TNode.cc b/helm/DEVEL/mathml_editor/src/TNode.cc index 4235f3728..4523ced5d 100644 --- a/helm/DEVEL/mathml_editor/src/TNode.cc +++ b/helm/DEVEL/mathml_editor/src/TNode.cc @@ -129,6 +129,22 @@ TNode::replace(const TNode& newNode) const parent.replaceChild(newNode.node, node); } +void +TNode::replace(const TNode& first, const TNode& last) const +{ + assert(node); + assert(first); + + TNode p = first; + while (p != last) + { + TNode next = p.next(); + insert(p); + p = next; + } + remove(); +} + void TNode::insert(const TNode& newNode) const { diff --git a/helm/DEVEL/mathml_editor/src/TNode.hh b/helm/DEVEL/mathml_editor/src/TNode.hh index dde315d36..b2c68fa69 100644 --- a/helm/DEVEL/mathml_editor/src/TNode.hh +++ b/helm/DEVEL/mathml_editor/src/TNode.hh @@ -52,6 +52,7 @@ public: //void advance(const TNode&) const; void remove(void) const; void replace(const TNode&) const; + void replace(const TNode&, const TNode&) const; void insert(const TNode&) const; void append(const TNode&) const; void append(const TNode&, const TNode&) const; diff --git a/helm/DEVEL/mathml_editor/src/TPushParser.cc b/helm/DEVEL/mathml_editor/src/TPushParser.cc index cfcce849f..a063668e0 100644 --- a/helm/DEVEL/mathml_editor/src/TPushParser.cc +++ b/helm/DEVEL/mathml_editor/src/TPushParser.cc @@ -80,6 +80,7 @@ TPushParser::do_end() // closing brace for a right-open macro (like \over) cursor.remove(); advance(parent.parent()); + frames.pop(); } else { @@ -410,6 +411,11 @@ TPushParser::do_control(const std::string& name) { TNode m = doc.createC(name, nextId++); cursor.replace(m); + + cout << "ecco tutti i token del pattern della entry inserita" << endl; + for (unsigned i = 0; i < entry.pattern.size(); i++) + cout << entry.pattern[i].value << endl; + if (entry.leftOpen && entry.rightOpen) { assert(entry.pattern.empty()); @@ -446,6 +452,7 @@ TPushParser::do_control(const std::string& name) if (parent.isG()) { frames.push(Frame(entry)); + cout << "do_control: valore di pos del frame inserito " << frames.top().pos << endl; if (entry.paramDelimited(0)) { TNode g = doc.createG(); @@ -481,16 +488,31 @@ TPushParser::do_control(const std::string& name) void TPushParser::gdelete_prev() { - // if in this function, the prev of cursor does exist, also the parent and we want a graphical deleting + // if in this function, the prev of cursor does exist, also the parent and we want a graphical deleting. + + assert(cursor.prev()); + assert(cursor.parent()); + TNode prev = cursor.prev(); if (prev.is("i") || prev.is("o") || prev.is("n")) { // the control below is designed to handle the case in which val have more than one unicode character DOM::UCS4String ucs4val(prev.element().getAttribute("val")); - if (ucs4val.length() <= 1) + if ((ucs4val.length() <= 1) || prev.element().hasAttribute("name")) { cursor.remove(); prev.replace(cursor); + + if (cursor.parent().isC()) + { + // in this case we have removed an element of a MACRO. + // we can assert that this element was a non delimited argument + assert(!frames.empty()); + Frame& frame = frames.top(); + assert(frame.pos > 0); + + frame.pos--; + } } else { @@ -502,7 +524,7 @@ TPushParser::gdelete_prev() { cursor.remove(); prev.append(cursor); - do_gdelete(); + gdelete_prev(); } // end of if (prev.is("sp") || prev.is("sb")) else if (prev.isG()) { @@ -512,9 +534,73 @@ TPushParser::gdelete_prev() } else if (prev.isC()) { -// cursor.remove(); -// prev.append(cursor); -// do_gdelete(); + const TDictionary::Entry& entry = dictionary.find(prev["name"]); + + // i start to remove a MACRO. The frame associated to this MACRO was + // popped from the stack (i think). So, i re-push the frame in the stack, + // but the pos member should be set correctly + cout << "gdelete_prev: i have to start to delete a MACRO" << endl; + + // if the control element is leftOpen and rightOpen, the cursor should be placed after + // the last child of the control element's last child + if (entry.rightOpen) + { + cout << "gdelte_prev(): i have to delete a control rightOpen, so i push an element in the stack" << endl; + Frame frame(entry); + frames.push(frame); + + cursor.remove(); + prev.last().append(cursor); + do_gdelete(); + } + else if (entry.leftOpen) + { + cout << "gdelete_prev: i have to delete a control element with leftOpen" << endl; + assert(prev.first()); + assert(prev.first().isG()); + assert(prev.first() == prev.last()); + TNode g = prev.first(); + g.remove(); + prev.replace(g.first(), TNode()); + } + else if (!entry.pattern.empty()) + { + // we have to start removing a MACRO which accepts arguments. + // a MACRO without child does not exist + + cout << "gdelete_prev: i have to remove a MACRO with argument" << endl; + + assert(prev.size() >= 1); + + if (prev.last().isG() && !prev.last().hasId()) + { + // this means that the last child of the MACRO is a phantom group, + // which in turn means that it is a delimited argument + // so we have to ideally remove this delimiter + cursor.remove(); + prev.last().append(cursor); + // i have to push a frame with a correct value of pos + Frame frame(entry); + frame.pos = entry.pattern.size() - 2; + frames.push(frame); + } + else + { + // in this case, the last child of the MACRO is + // an argument which is NOT delimited, so i try to + // remove it + cout << "gdelete_prev: i try to remove the last argumet of the MACRO" << endl; + cursor.remove(); + prev.append(cursor); // now prev is the cursor's parent + + Frame frame(entry); + frame.pos = entry.pattern.size(); + frames.push(frame); + + gdelete_prev(); + + } + } } else { @@ -523,11 +609,45 @@ TPushParser::gdelete_prev() } // end of method +void +TPushParser::rgreplace_futher(void) +{ + // this function MUST only be invoked, when the cursor + // is the only child of a group with id. This function + // replace the group with the cursor. But if the new parent + // is a group with id and the cursor is the only child of the + // group, the new parent is replaced...and so on. + // r stands for recursive, g stands for graphical + assert(cursor.parent()); + assert(cursor.parent().isG() && cursor.parent().hasId()); + + TNode parent = cursor.parent(); + + while (parent.isG() && parent.hasId() && (parent.first() == cursor)) + { + parent.replace(cursor); + parent = cursor.parent(); + } + + if (parent.isC()) + { + // in this case we have removed a MACRO's child. + // I can assert that this MACRO accepts arguments. + assert(!frames.empty()); + Frame& frame = frames.top(); + assert(frame.pos > 0); + frame.pos--; + } +} + void TPushParser::do_gdelete() { // this function operates a graphical deleting + //if (!frames.empty()) + // cout << "do_gdelete: c'e' un frame aperto e il suo pos vale: " << frames.top().pos << endl; + TNode parent = cursor.parent(); // if no parent, do nothing @@ -541,57 +661,238 @@ TPushParser::do_gdelete() { // i try to delete the preceding element gdelete_prev(); - - // if gdelete_prev has removed all parent's child, and the group has Id, it should be removed. - // this control should be re-done on the new parent and so on. - while ((parent.first() == cursor) && parent.isG() && parent.hasId()) - { - cursor.remove(); - parent.replace(cursor); - parent = cursor.parent(); - } + + if ((parent.first() == cursor) && parent.isG() && parent.hasId()) + rgreplace_futher(); + } else // no previous node is present { - if (!parent.parent().is("math")) + // if here, we are in a gruop whose only child is the cursor. + + if (!parent.hasId()) { - cursor.remove(); - parent.replace(cursor); - - // if the new parent is a group with Id, it should be removed - if (cursor.parent().isG() && cursor.parent().hasId()) do_gdelete(); + // the parent is a phantom group + assert(parent.parent()); + if (!parent.parent().is("math")) + { + TNode gfuther = parent.parent(); + + // if the grand futher is a group with Id, it should be removed, + // but i don't know if it will never occur... + if (gfuther.isG() && gfuther.hasId()) + { + cursor.remove(); + parent.replace(cursor); + + // re-start the process + do_gdelete(); + } + else if (gfuther.isC()) + { + // the grand futher is a control element: since the parent is a phantom group, + // the TML tree should be in a inconsistent state (once removed the parent). + + // being here means that there is a frame in the stack + assert(!frames.empty()); + cout << "do_gdelete: i have to remove a phantom group whuch is a child of a MACRO" << endl; + Frame& frame = frames.top(); + if (frame.entry.leftOpen && frame.entry.rightOpen) + { + // in this case, the cursor is in the second and last child + // of the MACRO. We can assert that the grand futher has two + // children. which are both phantom group + cout << "do_gdelete: the MACRO is leftOpen and rigthOpen" << endl; + assert(gfuther.size() == 2); + assert((gfuther.last() == parent) && (gfuther.first().isG() && !gfuther.first().hasId())); + assert(frame.pos == 0); + + TNode ggfuther = gfuther.parent(); + assert(ggfuther); + cursor.remove(); + parent.remove(); + // i have to replace the gfuther with the elements of its first child + gfuther.replace(gfuther.first().first(), TNode()); + cout << "do_gdelete: i have removed the control element, and replaced it with its first child" << endl; + ggfuther.append(cursor); + cout << "do_gdelete: cursor appended to the grand grand futher" << endl; + + // now we have the situation preceding the insertion of the MACRO leftOpen and rightOpen + // this MACRO no longer exists. + frames.pop(); + } + else if (frame.entry.rightOpen) + { + // the user has inserted a MACRO rightOpen. Since the cursor is the + // only child of the MACRO, the user want to remove it. + // We can assert that cursor's parent is the only child of the MACRO + cout << "do_gdelete: the MACRO is rightOpen only" << endl; + assert(gfuther.size() == 1); + assert(frame.pos == 0); // i think this assert has no sense + + cursor.remove(); + parent.remove(); + gfuther.replace(cursor); + + // now we have the situation preceding the MACRO rightOpen, so i have to pop the frame + frames.pop(); + } + else if (frame.entry.leftOpen) + { + // it' s an unpredicted situation + cout << "it's a bad situation, maybe handlable, but unpredicted" << endl; + } + else if (!frame.entry.pattern.empty()) + { + // the MACRO (the cursor's grand futher) accepts arguments. + // we have to control if the cursor's uncle does exist. + + if (parent.prev()) + { + // in this case, we can assert that frame in the stack has + // pos greater than 0 + assert(frame.pos > 0); + + // cursor's uncle does exist. we have to control + // its nature (is it a phantom group?) + TNode uncle = parent.prev(); + if (uncle.isG() && !uncle.hasId()) + { + // the cursor's parent is a phantom group, so it was a + // delimited argument of the MACRO and the corrisponding + // delimeter is inserted. So, the action of deleting means + // removing this delimeter + cursor.remove(); + parent.remove(); + uncle.append(cursor); + frame.pos -= 2; + } + else + { + // the uncle was a NOT delimited argument. So i try to + // remove it + cursor.remove(); + parent.replace(cursor); + + parent = cursor.parent(); // i update the parent (it should be the MACRO) + assert(parent.isC()); + + gdelete_prev(); + + } + } + else + { + // cursor's parent is the only child of the MACRO, which accepts arguments + // i can assert that frame.pos == 0. + // In this case i can replace the MACRO with the cursor + assert(frame.pos == 0); + + cursor.remove(); + parent.remove(); + gfuther.replace(cursor); + + frames.pop(); + } + + } + } + } + else // the grand futher is math + { + // nothing to do...i think + assert(frames.empty()); + } } else - { - // nothing to do...i think + { + // the parent is a group with id and has no elements other than cursor + // so we replace it with the cursor. + rgreplace_futher(); + + // i have to re-start the process, because it' a graphical delete + do_gdelete(); } } } else if (parent.isC()) { - // i think i have to implement different behaviors based on the attribute name and/or left-open - } - else if (parent.is("sp") || parent.is("sb")) - { - // being here means that a prev MUST exist - + // being here means that there is an open frame for the control element + // and this element is closed at either side (no leftOpen no rightOpen) + // and the MACRO was waiting for a non delimited argument, so + // we can assert that frame.entry.pattern.size() >= 1 + assert(!frames.empty()); + Frame& frame = frames.top(); + + assert(frame.entry.pattern.size() >= 1); + + cout << "do_gdelete: frames.top().pos = " << frames.top().pos << endl; + TNode prev = cursor.prev(); - if (!prev) cout << "qualcosa non va" << endl; + if (!prev) + { + // in this case we can replace the MACRO with the cursor + // and pop the stack and we can assert that frame.pos == 0 + assert(frame.pos == 0); + cursor.remove(); // it should not be necessary, but i'm not shure + parent.replace(cursor); + frames.pop(); + } else { - if (parent.first().next() == cursor) // there's only an element preceding the cursor + // in this case the cursor has a preceding element + // and there are differnt things based on the nature + // of the prev: if it's a phantom group do something, + // else do something else + if (prev.isG() && !prev.hasId()) { + // in this case we have to append the cursor + // to the prev and decrement frame.pos of two units + // because the prev is a delimited argument and the + // delimiter is inserted. So we ideally remove this delimiter cursor.remove(); - parent.replace(prev); - prev.parent().append(cursor); + prev.append(cursor); + frame.pos -=2; } - else // there are two elements preceding the cursor + else { + // the prev is an non delimited argument, so we try to + // remove it. gdelete_prev(); } } } + else if (parent.is("sp") || parent.is("sb")) + { + // being here means that a prev MUST exist + // and that there is only an element preceding the cursor. + // A sp's (or sb's) MUST NOT be a MACRO + + assert(parent.size() == 2); + assert(parent.parent() && !parent.parent().isC()); + + TNode prev = cursor.prev(); + cursor.remove(); + if (prev.isG() && !prev.hasId() && (prev.size() == 0)) + { + prev.remove(); + parent.replace(cursor); + + // now, cursor should be the only parent's child + assert(cursor.parent().size() == 1); + + if (cursor.parent().isG() && cursor.parent().hasId()) rgreplace_futher(); + } + else + { + assert(prev.hasId()); + parent.replace(prev); + prev.parent().append(cursor); + // now prev should have a preceding element + assert(cursor.parent().size() > 1); + } + } else { // not handled: no control for tables, ... @@ -599,7 +900,9 @@ TPushParser::do_gdelete() } else { - // do nothing ?? + // the cursro has no parent!!! + // do nothing? + // emit an error? and if we want to emit an error, in which way? } } // end of method @@ -632,9 +935,19 @@ void TPushParser::push(const TToken& token) { cerr << "TPushParser::push " << token.value << " (cat: " << token.category << ")" << endl; + + if (token.category == TToken::GDELETE) + { + cout << "push: i have to process a token with category member = GDELETE" << endl; + process(token); + } + else + { + TNode parent = cursor.parent(); // If the cursor has no parent then it is detached from the editing // tree, which means this token will be ignored + if (parent) // If the parent is a phantom group and the grand-parent is a // control sequence, there are two cases: @@ -704,6 +1017,8 @@ TPushParser::push(const TToken& token) // or a fixed token Frame& frame = frames.top(); assert(frame.pos < frame.entry.pattern.size()); + + cout << "push: il valore di pos del frame inserito prima e': " << frame.pos << endl; if (frame.entry.pattern[frame.pos].category == TToken::PARAMETER) { // As by the TeX parsing rules of undelimited parameters, @@ -749,7 +1064,12 @@ TPushParser::push(const TToken& token) cout << "ignored token" << endl; } + } // this end corresponds to the else of the if (token.category == GDELETE) + if (listener) listener->callback(doc); + + if (frames.empty()) cout << "stack vuoto" << endl; + else cout << "stack non vuoto" << endl; } void diff --git a/helm/DEVEL/mathml_editor/src/TPushParser.hh b/helm/DEVEL/mathml_editor/src/TPushParser.hh index c3cee66c8..951fb874a 100644 --- a/helm/DEVEL/mathml_editor/src/TPushParser.hh +++ b/helm/DEVEL/mathml_editor/src/TPushParser.hh @@ -28,8 +28,6 @@ private: std::string PRIME(void) const; bool isPrimes(const TNode&) const; - void gdelete_prev(void); - void do_begin(void); void do_end(void); void do_shift(void); @@ -45,6 +43,8 @@ private: void do_active(const std::string&); void do_comment(void); void do_control(const std::string&); + void gdelete_prev(void); + void rgreplace_futher(void); void do_gdelete(void); void do_cr(void); diff --git a/helm/DEVEL/mathml_editor/test/editor.cc b/helm/DEVEL/mathml_editor/test/editor.cc index 265d35e53..8ee408a3d 100644 --- a/helm/DEVEL/mathml_editor/test/editor.cc +++ b/helm/DEVEL/mathml_editor/test/editor.cc @@ -87,7 +87,7 @@ public: DOM::Document res = style.apply(doc.document(), dirtyId); assert(res); style.save(doc.document(), stdout); - style.save(res, stdout); + //style.save(res, stdout); if (result) { cout << "REPLACING A FRAGMENT OF THE DOCUMENT" << endl; @@ -98,10 +98,13 @@ public: if (result.get_documentElement().getAttribute("xref") == root.getAttribute("xref")) { cout << "REPLACING ROOT" << endl; + result.replaceChild(result.importNode(root, true), result.get_documentElement()); +#if 0 // the following remove should not be necessary // according to the spec replaceChild should work just fine result.removeChild(result.get_documentElement()); result.appendChild(result.importNode(root, true)); +#endif } else try @@ -130,6 +133,7 @@ public: if (GUI_load_document(gdome_cast_doc(static_cast(result))) < 0) cerr << "c'e' stato un errore" << endl; } + style.save(result, stdout); doc.clearDirty(); } diff --git a/helm/DEVEL/mathml_editor/test/guiGTK.c b/helm/DEVEL/mathml_editor/test/guiGTK.c index d270f7448..88b85f8b5 100644 --- a/helm/DEVEL/mathml_editor/test/guiGTK.c +++ b/helm/DEVEL/mathml_editor/test/guiGTK.c @@ -1,4 +1,28 @@ - +/* + * Copyright (C) 2000, Luca Padovani . + * + * This file is part of GtkMathView, a Gtk widget for MathML. + * + * GtkMathView 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. + * + * GtkMathView 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 GtkMathView; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * For details, see the GtkMathView World-Wide-Web page, + * http://cs.unibo.it/~lpadovan/mml-widget, or send a mail to + * + */ + +#include #include #include #include @@ -14,59 +38,52 @@ static GtkWidget* scrolled_area; static GtkWidget* status_bar; static GtkMenuItem* anti_aliasing_item; static GtkMenuItem* transparency_item; -static GtkMenuItem* font_size_item; static GdkCursor* normal_cursor; static GdkCursor* link_cursor; static gchar* doc_name = NULL; static GdomeElement* root_selected = NULL; -static GdomeElement* first_selected = NULL; -static GdomeElement* last_selected = NULL; -static GdomeElement* cursor = NULL; -static gboolean selecting = FALSE; -static gboolean button_pressed = FALSE; static guint statusbar_context; -static guint edit_timeout_id; -static GdomeElement* cursor_ptr = NULL; -static gboolean cursor_active = FALSE; - static void create_widget_set(gpointer); static GtkWidget* get_main_menu(void); -static void options_selection_mode(GtkWidget*, guint); -static void options_font_size(GtkWidget*, guint); +static void file_open(GtkWidget*, gpointer); +static void file_re_open(GtkWidget*, gpointer); +static void file_close(GtkWidget*, gpointer); +static void options_font_manager(GtkWidget*, FontManagerId); +static void options_set_font_size(GtkWidget*, gpointer); +static void options_change_font_size(GtkWidget*, gboolean); static void options_verbosity(GtkWidget*, guint); static void options_anti_aliasing(GtkWidget*, gpointer); static void options_transparency(GtkWidget*, gpointer); -static void edit_delete_selection(GtkWidget*, gpointer); -static void edit_select_parent(GtkWidget*, gpointer); +static void selection_delete(GtkWidget*, gpointer); +static void selection_parent(GtkWidget*, gpointer); +static void selection_reset(GtkWidget*, gpointer); static void help_about(GtkWidget*, gpointer); -extern int edit_timeout(gpointer); -extern void push_char(gpointer, gchar); - static GtkItemFactoryEntry menu_items[] = { { "/_File", NULL, NULL, 0, "" }, + { "/File/_Open...", "O", file_open, 0, NULL }, + { "/File/_Reopen", NULL, file_re_open, 0, NULL }, + { "/File/_Close", "W", file_close, 0, NULL }, + { "/File/sep1", NULL, NULL, 0, "" }, { "/File/_Quit", "Q", gtk_main_quit, 0, NULL }, - { "/_Edit", NULL, NULL, 0, "" }, - { "/Edit/Delete Selection", NULL, edit_delete_selection, 0, NULL }, - { "/Edit/Select Parent", NULL, edit_select_parent, 0, NULL }, + { "/_Selection", NULL, NULL, 0, "" }, + { "/Selection/Reset", NULL, selection_reset, 0, NULL }, + { "/Selection/Delete", NULL, selection_delete, 0, NULL }, + { "/Selection/Select Parent", NULL, selection_parent, 0, NULL }, { "/_Options", NULL, NULL, 0, "" }, - { "/Options/_Selection Mode", NULL, NULL, 0, "" }, - { "/Options/Selection Mode/_Structure", NULL, options_selection_mode, 0, "" }, - { "/Options/Selection Mode/_Linear", NULL, options_selection_mode, 1, "/Options/Selection Mode/Structure" }, { "/Options/Default _Font Size", NULL, NULL, 0, "" }, - { "/Options/Default Font Size/8pt", NULL, options_font_size, 8, "" }, - { "/Options/Default Font Size/10pt", NULL, options_font_size, 10, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/12pt", NULL, options_font_size, 12, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/14pt", NULL, options_font_size, 14, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/18pt", NULL, options_font_size, 18, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/24pt", NULL, options_font_size, 24, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/48pt", NULL, options_font_size, 48, "/Options/Default Font Size/8pt" }, - { "/Options/Default Font Size/72pt", NULL, options_font_size, 72, "/Options/Default Font Size/8pt" }, + { "/Options/Default Font Size/Set...", NULL, options_set_font_size, 0, NULL }, + { "/Options/Default Font Size/sep1", NULL, NULL, 0, "" }, + { "/Options/Default Font Size/Larger", NULL, options_change_font_size, TRUE, NULL }, + { "/Options/Default Font Size/Smaller", NULL, options_change_font_size, FALSE, NULL }, + { "/Options/Font Manager", NULL, NULL, 0, "" }, + { "/Options/Font Manager/_GTK", NULL, options_font_manager, FONT_MANAGER_GTK, "" }, + { "/Options/Font Manager/_Type 1", NULL, options_font_manager, FONT_MANAGER_T1, "/Options/Font Manager/GTK" }, { "/Options/Verbosity", NULL, NULL, 0, "" }, { "/Options/Verbosity/_Errors", NULL, options_verbosity, 0, "" }, { "/Options/Verbosity/_Warnings", NULL, options_verbosity, 1, "/Options/Verbosity/Errors" }, @@ -116,31 +133,6 @@ load_error_msg(const char* name) g_free(msg); } -static void -cursor_off() -{ - if (cursor_active) - { - cursor_active = FALSE; - if (cursor_ptr != NULL && - gtk_math_view_is_selected(main_area, cursor_ptr)) - gtk_math_view_reset_selection(main_area, cursor_ptr); - } -} - -static void -cursor_on() -{ - if (!cursor_active) - { - cursor_active = FALSE; - if (cursor_ptr != NULL && - !gtk_math_view_is_selected(main_area, cursor_ptr)) - gtk_math_view_set_selection(main_area, cursor_ptr); - cursor_active = TRUE; - } -} - void GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpointer context) { @@ -163,7 +155,6 @@ GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpoint void GUI_uninit() { - gtk_timeout_remove(edit_timeout_id); } int @@ -182,22 +173,6 @@ GUI_load_document(GdomeDocument* doc) return 0; } -int -GUI_load_uri(const char* uri) -{ - GtkMathView* math_view; - - g_return_val_if_fail(uri != NULL, -1); - g_return_val_if_fail(main_area != NULL, -1); - g_return_val_if_fail(GTK_IS_MATH_VIEW(main_area), -1); - - math_view = GTK_MATH_VIEW(main_area); - - if (!gtk_math_view_load_uri(math_view, uri)) return -1; - - return 0; -} - void GUI_freeze() { @@ -235,22 +210,87 @@ GUI_run() gtk_main(); } +void +GUI_set_font_manager(FontManagerId id) +{ + gboolean t1; + GtkMathView* math_view; + + g_return_if_fail(id != FONT_MANAGER_UNKNOWN); + g_return_if_fail(main_area != NULL); + g_return_if_fail(GTK_IS_MATH_VIEW(main_area)); + + t1 = id == FONT_MANAGER_T1; + + math_view = GTK_MATH_VIEW(main_area); + + gtk_math_view_freeze(math_view); + + if (id != gtk_math_view_get_font_manager_type(math_view)) + gtk_math_view_set_font_manager_type(math_view, id); + + gtk_widget_set_sensitive(anti_aliasing_item, t1); + gtk_widget_set_sensitive(transparency_item, t1); + + if (t1) + { + gtk_math_view_set_anti_aliasing(math_view, GTK_CHECK_MENU_ITEM(anti_aliasing_item)->active); + gtk_math_view_set_transparency(math_view, GTK_CHECK_MENU_ITEM(transparency_item)->active); + } + + gtk_math_view_thaw(math_view); +} + static void -options_selection_mode(GtkWidget* widget, guint mode) +store_filename(GtkFileSelection* selector, GtkWidget* user_data) { + gchar* selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(user_data)); + if (selected_filename != NULL) + GUI_load_document(selected_filename); } static void -options_font_size(GtkWidget* widget, guint size) +file_close(GtkWidget* widget, gpointer data) { - GtkMathView* math_view; + GUI_unload_document(); +} - g_return_if_fail(main_area != NULL); - g_return_if_fail(GTK_IS_MATH_VIEW(main_area)); +static void +file_re_open(GtkWidget* widget, gpointer data) +{ + if (doc_name != NULL) { + GUI_load_document(doc_name); + } +} - math_view = GTK_MATH_VIEW(main_area); +static void +file_open(GtkWidget* widget, gpointer data) +{ + GtkWidget* fs = gtk_file_selection_new("Open File"); + + gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", GTK_SIGNAL_FUNC (store_filename), (gpointer) fs); + + /* Ensure that the dialog box is destroyed when the user clicks a button. */ + + gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), + (gpointer) fs); + + gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), + (gpointer) fs); + + /* Display that dialog */ + + gtk_widget_show (fs); +} - gtk_math_view_set_font_size(math_view, size); +static void +options_font_manager(GtkWidget* widget, FontManagerId id) +{ + g_return_if_fail(id != FONT_MANAGER_UNKNOWN); + GUI_set_font_manager(id); } static void @@ -274,7 +314,7 @@ options_verbosity(GtkWidget* widget, guint level) } static void -edit_delete_selection(GtkWidget* widget, gpointer data) +selection_delete(GtkWidget* widget, gpointer data) { if (root_selected != NULL) { @@ -290,12 +330,12 @@ edit_delete_selection(GtkWidget* widget, gpointer data) } static void -edit_select_parent(GtkWidget* widget, gpointer data) +selection_parent(GtkWidget* widget, gpointer data) { if (root_selected != NULL) { GdomeException exc = 0; - GdomeElement* parent = gdome_cast_el(gdome_n_parentNode(root_selected, &exc)); + GdomeElement* parent = gdome_n_parentNode(root_selected, &exc); g_assert(exc == 0); gdome_el_unref(root_selected, &exc); g_assert(exc == 0); @@ -304,6 +344,19 @@ edit_select_parent(GtkWidget* widget, gpointer data) } } +static void +selection_reset(GtkWidget* widget, gpointer data) +{ + if (root_selected != NULL) + { + GdomeException exc = 0; + gtk_math_view_reset_selection(GTK_MATH_VIEW(main_area), root_selected); + gdome_el_unref(root_selected, &exc); + g_assert(exc == 0); + root_selected = NULL; + } +} + static void help_about(GtkWidget* widget, gpointer data) { @@ -312,7 +365,7 @@ help_about(GtkWidget* widget, gpointer data) GtkWidget* ok; dialog = gtk_dialog_new(); - label = gtk_label_new("\n MathML Viewer \n Copyright (C) 2000-2002 Luca Padovani \n"); + label = gtk_label_new("\n MathML Viewer \n Copyright (C) 2000-2003 Luca Padovani \n"); ok = gtk_button_new_with_label("Close"); gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", @@ -325,208 +378,152 @@ help_about(GtkWidget* widget, gpointer data) gtk_widget_show_all (dialog); } -#if 0 -#if defined(HAVE_GMETADOM) static void -element_changed(GtkMathView* math_view, GdomeElement* node) +change_default_font_size(GtkSpinButton* widget, GtkSpinButton* spin) { - GdomeException exc; - GdomeDOMString* name; - GdomeDOMString* ns_uri; - - g_return_if_fail(math_view != NULL); - g_return_if_fail(GTK_IS_MATH_VIEW(math_view)); - - name = gdome_str_mkref("href"); - ns_uri = gdome_str_mkref(XLINK_NS_URI); - - while (node != NULL && !gdome_el_hasAttributeNS(node, ns_uri, name, &exc)) - node = gdome_cast_el(gdome_el_parentNode(node, &exc)); - - if (node != NULL && gdome_el_hasAttributeNS(node, ns_uri, name, &exc)) - gdk_window_set_cursor(GTK_WIDGET(math_view)->window, link_cursor); - else - gdk_window_set_cursor(GTK_WIDGET(math_view)->window, normal_cursor); - - gdome_str_unref(name); - gdome_str_unref(ns_uri); + g_return_if_fail(spin != NULL); + gtk_math_view_set_font_size( GTK_MATH_VIEW(main_area), gtk_spin_button_get_value_as_int(spin)); } -#endif static void -#if defined(HAVE_GMETADOM) -action_changed(GtkMathView* math_view, GdomeElement* node) -#endif +options_change_font_size(GtkWidget* widget, gboolean larger) { - g_return_if_fail(math_view != NULL); - g_return_if_fail(GTK_IS_MATH_VIEW(math_view)); + gfloat size = gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area)); + if (larger) size = size / 0.71; + else size = size * 0.71; + if (size < 1) size = 1; + gtk_math_view_set_font_size (GTK_MATH_VIEW(main_area), (gint) size + 0.5); } static void -#if defined(HAVE_GMETADOM) -selection_changed(GtkMathView* math_view, GdomeElement* node) -#endif +options_set_font_size(GtkWidget* widget, gpointer data) { - g_return_if_fail(math_view != NULL); - g_return_if_fail(GTK_IS_MATH_VIEW(math_view)); - gtk_math_view_set_selection(math_view, node); + GtkWidget* dialog; + GtkWidget* label; + GtkWidget* ok; + GtkWidget* cancel; + GtkWidget* spin; + GtkObject* adj; + + dialog = gtk_dialog_new(); + label = gtk_label_new("Default font size:"); + ok = gtk_button_new_with_label("OK"); + cancel = gtk_button_new_with_label("Cancel"); - cursor_off(); - cursor_ptr = node; - cursor_on(); + adj = gtk_adjustment_new (gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area)), 1, 200, 1, 1, 1); + spin = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 1, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); + + gtk_signal_connect (GTK_OBJECT (ok), "clicked", + GTK_SIGNAL_FUNC (change_default_font_size), (gpointer) spin); + + gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); + + gtk_signal_connect_object (GTK_OBJECT (ok), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); + + gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); + + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5); + + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), spin); + + gtk_widget_show_all (dialog); } +#if 0 #if defined(HAVE_GMETADOM) static void -clicked(GtkMathView* math_view, gpointer user_data) +element_changed(GtkMathView* math_view, GdomeElement* elem) { - GdomeException exc; - GdomeDOMString* name; - GdomeDOMString* ns_uri; - GdomeElement* p; + GdomeDOMString* link = NULL; g_return_if_fail(math_view != NULL); + g_return_if_fail(GTK_IS_MATH_VIEW(math_view)); - name = gdome_str_mkref("href"); - ns_uri = gdome_str_mkref(XLINK_NS_URI); - - p = gtk_math_view_get_element(math_view); - while (p != NULL && !gdome_el_hasAttributeNS(p, ns_uri, name, &exc)) - p = gdome_cast_el(gdome_el_parentNode(p, &exc)); +/* printf("pointer is on %p\n", elem); */ - if (p != NULL) { - GdomeDOMString* href = gdome_el_getAttributeNS(p, ns_uri, name, &exc); - g_assert(href != NULL); + link = find_hyperlink(elem, XLINK_NS_URI, "href"); + if (link != NULL) + gdk_window_set_cursor(GTK_WIDGET(math_view)->window, link_cursor); + else + gdk_window_set_cursor(GTK_WIDGET(math_view)->window, normal_cursor); - GUI_load_document(href->str); - gdome_str_unref(href); - } else if (gtk_math_view_get_action(math_view) != NULL) - gtk_math_view_action_toggle(math_view); + if (link != NULL) + gdome_str_unref(link); } #endif #endif -static gint -button_press_event(GtkWidget* widget, - GdkEventButton* event, - GtkMathView* math_view) +static void +selection_changed(GtkMathView* math_view, GdomeElement* first, GdomeElement* last) { - g_return_val_if_fail(event != NULL, FALSE); - g_return_val_if_fail(math_view != NULL, FALSE); - - if (event->button == 1) - { - GdomeException exc; + g_return_if_fail(math_view != NULL); + g_return_if_fail(GTK_IS_MATH_VIEW(math_view)); + g_return_if_fail(first != NULL); + +/* printf("selection changed %p %p\n", first, last); */ - cursor_off(); + if (last != NULL) + { + GdomeException exc = 0; if (root_selected != NULL) { - gtk_math_view_reset_selection(math_view, root_selected); gdome_el_unref(root_selected, &exc); g_assert(exc == 0); - root_selected = NULL; - } - - if (first_selected != NULL) - { - gdome_el_unref(first_selected, &exc); - g_assert(exc == 0); } - if (last_selected != NULL) - { - gdome_el_unref(last_selected, &exc); - g_assert(exc == 0); - last_selected = NULL; - } - - first_selected = gtk_math_view_get_element_at(math_view, event->x, event->y); - button_pressed = TRUE; - selecting = FALSE; + root_selected = find_common_ancestor(first, last); +/* printf("selecting root %p\n", first, last, root_selected); */ + gtk_math_view_set_selection(math_view, root_selected); + g_assert(exc == 0); } - - return FALSE; } -static gint -motion_notify_event(GtkWidget* widget, - GdkEventMotion* event, - GtkMathView* math_view) +#if 0 +#if defined(HAVE_GMETADOM) +static void +clicked(GtkMathView* math_view, GdomeElement* elem) { - g_return_val_if_fail(event != NULL, FALSE); - g_return_val_if_fail(math_view != NULL, FALSE); - - if (button_pressed && first_selected != NULL) - { - GdomeException exc; - GdomeElement* el = gtk_math_view_get_element_at(math_view, event->x, event->y); - GdomeElement* root; - - selecting = TRUE; + GdomeException exc; + GdomeDOMString* name; + GdomeDOMString* ns_uri; + GdomeElement* p; - if (el != NULL && el != last_selected) - { - if (last_selected != NULL) - { - gdome_el_unref(last_selected, &exc); - g_assert(exc == 0); - } + g_return_if_fail(math_view != NULL); - last_selected = el; - } + /* printf("clicked on %p\n", elem); */ - if (last_selected != NULL) + if (elem != NULL) + { + GdomeElement* action; + GdomeDOMString* href = find_hyperlink(elem, XLINK_NS_URI, "href"); + if (href != NULL) { - root = find_common_ancestor(first_selected, last_selected); - g_assert(root != NULL); - - if (root != root_selected) - { - gtk_math_view_freeze(math_view); - if (root_selected != NULL) - { - gtk_math_view_reset_selection(math_view, root_selected); - gdome_el_unref(root_selected, &exc); - g_assert(exc == 0); - } - root_selected = root; - gtk_math_view_set_selection(math_view, root_selected); - gtk_math_view_thaw(math_view); - } - else - { - gdome_el_unref(root, &exc); - g_assert(exc == 0); - } +/* printf("hyperlink %s\n", href->str); */ + gdome_str_unref(href); } - } - - return FALSE; -} -static gint -button_release_event(GtkWidget* widget, - GdkEventButton* event, - GtkMathView* math_view) -{ - g_return_val_if_fail(event != NULL, FALSE); - g_return_val_if_fail(math_view != NULL, FALSE); - - if (event->button == 1) - { - if (!selecting) + action = find_self_or_ancestor(elem, MATHML_NS_URI, "maction"); +/* printf("action? %p\n", action); */ + if (action != NULL) { - cursor_ptr = first_selected; - cursor_on(); + gtk_math_view_freeze(math_view); + action_toggle(action); + gtk_math_view_thaw(math_view); + gdome_el_unref(action, &exc); + g_assert(exc == 0); } - - button_pressed = FALSE; - selecting = FALSE; } - - return FALSE; } +#endif +#endif static gboolean key_press_event(gpointer context, @@ -611,18 +608,6 @@ create_widget_set(gpointer context) (gpointer) main_area); #endif - gtk_signal_connect_object (GTK_OBJECT (main_area), - "button_press_event", GTK_SIGNAL_FUNC(button_press_event), - (gpointer) main_area); - - gtk_signal_connect_object (GTK_OBJECT (main_area), - "button_release_event", GTK_SIGNAL_FUNC(button_release_event), - (gpointer) main_area); - - gtk_signal_connect_object (GTK_OBJECT (main_area), - "motion_notify_event", GTK_SIGNAL_FUNC(motion_notify_event), - (gpointer) main_area); - gtk_signal_connect_object (GTK_OBJECT(window), "key_press_event", GTK_SIGNAL_FUNC(key_press_event), context); @@ -650,9 +635,62 @@ create_widget_set(gpointer context) if (gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area))) gtk_menu_item_activate(anti_aliasing_item); +} + +#if 0 +static void +create_widget_set() +{ + GtkWidget* main_vbox; + GtkWidget* menu_bar; + + main_vbox = gtk_vbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(main_vbox), 1); + gtk_container_add(GTK_CONTAINER(window), main_vbox); + gtk_widget_show(main_vbox); + + menu_bar = get_main_menu(); + gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0); + gtk_widget_show(menu_bar); - gtk_menu_item_activate(font_size_item); + main_area = gtk_math_view_new(NULL, NULL); + gtk_widget_show(main_area); + + gtk_signal_connect_object (GTK_OBJECT (main_area), + "selection_changed", GTK_SIGNAL_FUNC (selection_changed), + (gpointer) main_area); + + gtk_signal_connect_object (GTK_OBJECT (main_area), + "element_changed", GTK_SIGNAL_FUNC (element_changed), + (gpointer) main_area); + + gtk_signal_connect_object (GTK_OBJECT (main_area), + "clicked", GTK_SIGNAL_FUNC(clicked), + (gpointer) main_area); + + gtk_widget_add_events(GTK_WIDGET(main_area), + GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK); + + scrolled_area = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_widget_show(scrolled_area); + gtk_container_add(GTK_CONTAINER(scrolled_area), main_area); + gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0); + + status_bar = gtk_statusbar_new(); + gtk_widget_show(status_bar); + gtk_box_pack_start(GTK_BOX(main_vbox), status_bar, FALSE, TRUE, 0); + statusbar_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "filename"); + + gtk_widget_show(main_vbox); + + if (gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area))) + gtk_menu_item_activate(anti_aliasing_item); } +#endif GtkWidget* get_main_menu() @@ -677,11 +715,5 @@ get_main_menu() menu_item = gtk_item_factory_get_widget(item_factory, "/Options/Transparency"); transparency_item = GTK_MENU_ITEM(menu_item); - /* !!!BEWARE!!! the default font size must be kept aligned with the definition - * in math-engine-configuration.xml - */ - menu_item = gtk_item_factory_get_widget(item_factory, "/Options/Default Font Size/12pt"); - font_size_item = GTK_MENU_ITEM(menu_item); - return gtk_item_factory_get_widget(item_factory, "
"); } diff --git a/helm/DEVEL/mathml_editor/xsl/tml-mmlp.xsl b/helm/DEVEL/mathml_editor/xsl/tml-mmlp.xsl index c5c41e157..69de8c52e 100644 --- a/helm/DEVEL/mathml_editor/xsl/tml-mmlp.xsl +++ b/helm/DEVEL/mathml_editor/xsl/tml-mmlp.xsl @@ -517,7 +517,7 @@ ̅ - > +