changeset 220:ad5c7a5c2c39

Add extention to the inkscape to edit one of the active/normal/click frame of a button. There is one unsolved issue. Users can not know the current frame easily unless they check the XML node editor. We should try to show something in the UI. However, I have no found any goo dway to do this. We may need to modify the inkscape directly for this function in the future.
author wycc@wycc-desktop
date Sun, 14 Dec 2008 11:23:34 +0800
parents 8d9d717c9300 (diff) a0a3196b1a05 (current diff)
children 5c70883c40d5
files inkscape/MB_EditActiveButton.py inkscape/MB_EditClickButton.py inkscape/MB_EditNormalButton.py inkscape/MB_button_select_click.inx inkscape/MB_button_select_normal.inx
diffstat 12 files changed, 481 insertions(+), 175 deletions(-) [+]
line wrap: on
line diff
--- a/examples/drag/main.c	Fri Dec 12 09:35:27 2008 +0800
+++ b/examples/drag/main.c	Sun Dec 14 11:23:34 2008 +0800
@@ -16,6 +16,7 @@
     int state;
     co_aix orx,ory;
     int start_x,start_y;
+    coord_t *cursor;
 };
 engine_t *engine_init()
 {
@@ -60,8 +61,8 @@
 
     en->start_x = mev->x;
     en->start_y = mev->y;
-    en->orx = en->menu->cursor->matrix[2];
-    en->ory = en->menu->cursor->matrix[5];
+    en->orx = en->cursor->matrix[2];
+    en->ory = en->cursor->matrix[5];
     printf("pressed %g %g\n",en->orx,en->ory);
     en->state = 1;
 }
@@ -78,8 +79,8 @@
 
     if (en->state) {
         printf("move to (%d %d)\n", mev->x,mev->y);
-        coord_move(en->menu->cursor,en->orx + (mev->x-en->start_x),en->ory + (mev->y-en->start_y));
-        rdman_coord_changed(en->rdman, en->menu->cursor);
+        coord_move(en->cursor,en->orx + (mev->x-en->start_x),en->ory + (mev->y-en->start_y));
+        rdman_coord_changed(en->rdman, en->cursor);
         /* Update changed part to UI. */
         rdman_redraw_changed(en->rdman);
     }
@@ -91,11 +92,15 @@
 
     en = engine_init();
     en->menu = menu_new(en->rdman, en->rdman->root_coord);
+    en->cursor = (coord_t *) MB_SPRITE_GET_OBJ(&en->menu->lsym.sprite, "star");
+    printf("en->cursor=%x star=%x\n",en->cursor,en->menu->star);
+    printf("sprite=%x\n",&en->menu->lsym.sprite);
+    printf("en->menu=%x\n",en->menu);
 
     /*
      * Register observers to subjects of events for objects.
      */
-    subject = coord_get_mouse_event(en->menu->cursor);
+    subject = coord_get_mouse_event(en->cursor);
     subject_add_event_observer(subject,  EVT_MOUSE_BUT_PRESS, cursor_press_handler, en);
     subject_add_event_observer(subject,  EVT_MOUSE_BUT_RELEASE, cursor_release_handler, en);
     subject_add_event_observer(subject,  EVT_MOUSE_MOVE, cursor_move_handler, en);
--- a/examples/drag/menu.svg	Fri Dec 12 09:35:27 2008 +0800
+++ b/examples/drag/menu.svg	Sun Dec 14 11:23:34 2008 +0800
@@ -15,16 +15,6 @@
    inkscape:version="0.46"
    sodipodi:docname="menu.svg"
    inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 526.18109 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="744.09448 : 526.18109 : 1"
-       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
-       id="perspective10" />
-  </defs>
   <sodipodi:namedview
      id="base"
      pagecolor="#ffffff"
@@ -45,6 +35,16 @@
      inkscape:window-height="725"
      inkscape:window-x="450"
      inkscape:window-y="154" />
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -61,8 +61,9 @@
      inkscape:groupmode="layer"
      id="layer1">
     <g
-       id="cursor"
-       inkscape:label="#g2382">
+       id="star"
+       inkscape:label="#g2382"
+       mbname="star">
       <path
          transform="translate(-257.14286,-237.14286)"
          inkscape:label="#path2383"
--- a/examples/dynamic/button.svg	Fri Dec 12 09:35:27 2008 +0800
+++ b/examples/dynamic/button.svg	Sun Dec 14 11:23:34 2008 +0800
@@ -29,7 +29,7 @@
      inkscape:cx="239.91999"
      inkscape:cy="667.92389"
      inkscape:document-units="px"
-     inkscape:current-layer="layer1"
+     inkscape:current-layer="g2430"
      showgrid="false"
      inkscape:window-width="1400"
      inkscape:window-height="978"
@@ -77,26 +77,6 @@
        inkscape:vp_y="0 : 1000 : 0"
        inkscape:vp_x="0 : 526.18109 : 1"
        sodipodi:type="inkscape:persp3d" />
-    <filter
-       inkscape:collect="always"
-       id="filter4376"
-       x="-0.035928786"
-       width="1.0718576"
-       y="-0.10908499"
-       height="1.21817">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="5.3893179"
-         id="feGaussianBlur4378" />
-    </filter>
-    <filter
-       inkscape:collect="always"
-       id="filter4833">
-      <feGaussianBlur
-         inkscape:collect="always"
-         stdDeviation="1.0722832"
-         id="feGaussianBlur4835" />
-    </filter>
   </defs>
   <metadata
      id="metadata7">
@@ -125,92 +105,90 @@
          x="235.71429"
          y="282.36218" /></text>
     <g
-       id="normal"
-       inkscape:label="#g6113"
-       transform="translate(460,87.142857)">
-      <rect
-         transform="matrix(0.3740158,0,0,0.5340908,-66.07426,-121.9757)"
-         ry="16"
-         rx="16"
-         y="235.93361"
-         x="181.42857"
-         height="118.57143"
-         width="360"
-         id="rect6048"
-         style="fill:#008fff;fill-opacity:1;filter:url(#filter4376)" />
-      <rect
-         ry="8.5454531"
-         rx="5.9842529"
-         y="0.60081911"
-         x="1.2485654"
-         height="63.327908"
-         width="134.64569"
-         id="rect6050"
-         style="fill:#008fff;fill-opacity:1" />
-      <rect
-         ry="8.5454531"
-         rx="5.9842529"
-         y="0.21933411"
-         x="0.7142942"
-         height="63.327908"
-         width="134.64569"
-         id="rect6052"
-         style="fill:#008fff;fill-opacity:1" />
-      <text
-         inkscape:label="#text4385"
-         id="text6054"
-         y="48.076523"
-         x="26.428562"
-         style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter4833);font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="48.076523"
-           x="26.428562"
-           id="tspan6056"
-           sodipodi:role="line">Line</tspan></text>
-    </g>
-    <g
-       id="active"
-       inkscape:label="#g6103"
-       transform="translate(102.85714,85.714284)">
-      <rect
-         transform="matrix(0.3740158,0,0,0.5340908,-66.788541,-122.68999)"
-         ry="16"
-         rx="16"
-         y="235.93361"
-         x="181.42857"
-         height="118.57143"
-         width="360"
-         id="rect4074"
-         style="fill:#0000ff;filter:url(#filter4376)" />
-      <rect
-         ry="8.5454531"
-         rx="5.9842529"
-         y="-0.11346204"
-         x="0.53429729"
-         height="63.327908"
-         width="134.64569"
-         id="rect3240"
-         style="fill:#0000ff" />
-      <rect
-         ry="8.5454531"
-         rx="5.9842529"
-         y="-0.49495196"
-         x="-3.9397582e-07"
-         height="63.327908"
-         width="134.64569"
-         id="rect3242"
-         style="fill:#0000ff;fill-opacity:1" />
-      <text
-         inkscape:label="#text4385"
-         id="title"
-         y="47.362209"
-         x="25.714287"
-         style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4833);font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           y="47.362209"
-           x="25.714287"
-           id="tspan4387"
-           sodipodi:role="line">Line</tspan></text>
+       transform="translate(20.000001,42.857139)"
+       id="btn"
+       frame="click"
+       mbname="btn">
+      <g
+         id="g2430"
+         mbname="btn"
+         transform="translate(-78.571429,44.285714)">
+        <g
+           frame="normal"
+           id="btn_normal"
+           mbname="btn_normal"
+           transform="translate(1.4285713e-7,-60)">
+          <rect
+             style="fill:#0000ff"
+             id="rect2493"
+             width="82.85714"
+             height="42.857143"
+             x="220"
+             y="69.505035"
+             rx="5.4543843"
+             ry="7.1427469" />
+          <text
+             xml:space="preserve"
+             style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+             x="232.85715"
+             y="99.505043"
+             id="text2495"><tspan
+               sodipodi:role="line"
+               id="tspan2497"
+               x="232.85715"
+               y="99.505043">Rect</tspan></text>
+        </g>
+        <g
+           frame="active"
+           id="btn_active"
+           mbname="btn_active"
+           transform="translate(-1.4285757,30.000005)">
+          <rect
+             style="fill:#00ffff"
+             id="rect2481"
+             width="82.85714"
+             height="42.857143"
+             x="220"
+             y="69.505035"
+             rx="5.4543843"
+             ry="7.1427469" />
+          <text
+             xml:space="preserve"
+             style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+             x="232.85715"
+             y="99.505043"
+             id="text2483"><tspan
+               sodipodi:role="line"
+               id="tspan2485"
+               x="232.85715"
+               y="99.505043">Rect</tspan></text>
+        </g>
+        <g
+           frame="click"
+           id="btn_click"
+           mbname="btn_click"
+           transform="translate(-1.4285715,117.14286)">
+          <rect
+             style="fill:#0000ff"
+             id="rect2488"
+             width="82.85714"
+             height="42.857143"
+             x="220"
+             y="69.505035"
+             rx="5.4543843"
+             ry="7.1427469" />
+          <text
+             xml:space="preserve"
+             style="font-size:24px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+             x="232.85715"
+             y="99.505043"
+             id="text2490"><tspan
+               sodipodi:role="line"
+               id="tspan2492"
+               x="232.85715"
+               y="99.505043">Rect</tspan></text>
+        </g>
+      </g>
     </g>
   </g>
   <g
--- a/examples/dynamic/main.c	Fri Dec 12 09:35:27 2008 +0800
+++ b/examples/dynamic/main.c	Sun Dec 14 11:23:34 2008 +0800
@@ -6,6 +6,7 @@
  */
 #include <stdio.h>
 #include <mb.h>
+#include <string.h>
 #include "menu.h"
 #include "button.h"
 
@@ -23,6 +24,120 @@
     shape_t *rect;
     co_aix rx,ry;
 };
+
+
+typedef struct _mb_button {
+    engine_t *en;
+    coord_t *root;
+    coord_t *active;
+    coord_t *normal;
+    coord_t *click;
+    void (*press)();
+    void *arg;
+} mb_button_t;
+
+
+#define COORD_SHOW(group) coord_show(group);rdman_coord_changed(en->rdman, group)
+#define COORD_HIDE(group) coord_hide(group);rdman_coord_changed(en->rdman, group)
+
+#define CMOUSE(e) (coord_get_mouse_event(e))
+
+
+
+static void mb_button_move(event_t *evt, void *arg) 
+{
+    mb_button_t *btn = (mb_button_t *) arg;
+    engine_t *en = btn->en;
+
+    
+    printf("Mouse move\n");
+    COORD_SHOW(btn->active);
+    rdman_coord_changed(btn->en->rdman,btn->root);
+    rdman_redraw_changed(btn->en->rdman);
+}
+static void mb_button_out(event_t *evt, void *arg) 
+{
+    mb_button_t *btn = (mb_button_t *) arg;
+    engine_t *en = btn->en;
+
+    printf("mouse out\n");
+    COORD_HIDE(btn->active);
+    rdman_coord_changed(btn->en->rdman,btn->root);
+    rdman_redraw_changed(btn->en->rdman);
+}
+
+void mb_button_show_active(const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg)
+{
+    mb_button_t *btn = (mb_button_t *) arg;
+    engine_t *en = btn->en;
+
+    COORD_HIDE(btn->click);
+    rdman_coord_changed(btn->en->rdman,btn->root);
+    rdman_redraw_changed(btn->en->rdman);
+}
+
+void mb_button_pressed(event_t *evt, void *arg)
+{
+    mb_button_t *btn = (mb_button_t *) arg;
+    engine_t *en = btn->en;
+    mb_timeval_t now,to;
+
+    printf("Pressed\n");
+    COORD_SHOW(btn->click);
+    rdman_coord_changed(en->rdman,en->button->root_coord);
+    rdman_redraw_changed(en->rdman);
+    get_now(&now);
+    MB_TIMEVAL_SET(&to, 0, 500);
+    MB_TIMEVAL_ADD(&to,&now);
+
+    mb_tman_timeout(X_MB_tman(btn->en->rt), &to, mb_button_show_active, arg);
+}
+mb_button_t *mb_button_new(engine_t *en,mb_sprite_t *sp, char *name)
+{
+    mb_button_t *btn = (mb_button_t *) malloc(sizeof(mb_button_t));
+    char *buf = (char *) malloc(strlen(name)+5);
+
+    btn->root = (coord_t *) MB_SPRITE_GET_OBJ(sp, name);
+    sprintf(buf, "%s_normal", name);
+    btn->normal = (coord_t *) MB_SPRITE_GET_OBJ(sp, buf);
+    if (btn->normal == NULL) {
+    	printf("Missing normal button, this is not a correct button\n");
+    }
+    sprintf(buf, "%s_active", name);
+    btn->active = (coord_t *) MB_SPRITE_GET_OBJ(sp, buf);
+    if (btn->active == NULL) {
+    	printf("Missing active button, this is not a correct button\n");
+    }
+    sprintf(buf, "%s_click", name);
+    btn->click = (coord_t *) MB_SPRITE_GET_OBJ(sp, buf);
+    if (btn->click == NULL) {
+    	printf("Missing click button, this is not a correct button\n");
+    }
+    btn->press = NULL;
+    // Show only the normal button
+    COORD_HIDE(btn->active);
+    COORD_HIDE(btn->click);
+    // Move to the same position
+    btn->active->matrix[2] = 200;
+    btn->active->matrix[5] = 200;
+    btn->normal->matrix[2] = 200;
+    btn->normal->matrix[5] = 200;
+    btn->click->matrix[2] = 200;
+    btn->click->matrix[5] = 200;
+    btn->en = en;
+    subject_add_event_observer(CMOUSE(btn->root), EVT_MOUSE_MOVE, mb_button_move,btn);
+    subject_add_event_observer(CMOUSE(btn->root), EVT_MOUSE_OUT, mb_button_out,btn);
+    subject_add_event_observer(CMOUSE(btn->root), EVT_MOUSE_BUT_RELEASE, mb_button_pressed,btn);
+    return btn;
+}
+
+
+void mb_button_add_onClick(mb_button_t *b, void (*h)(void *arg), void *arg)
+{
+    b->press = h;
+    b->arg = arg;
+}
+
 engine_t *engine_init()
 {
 
@@ -50,51 +165,7 @@
     X_MB_free(en->rt);
     free(en);
 }
-#define COORD_SHOW(group) coord_show(group);rdman_coord_changed(en->rdman, group)
-#define COORD_HIDE(group) coord_hide(group);rdman_coord_changed(en->rdman, group)
 
-#define CMOUSE(e) (coord_get_mouse_event(e))
-
-
-
-static void button_move(event_t *evt, void *arg) 
-{
-    engine_t *en = (engine_t *) arg;
-
-    
-    printf("Mouse move\n");
-    COORD_SHOW(en->button->active);
-    rdman_coord_changed(en->rdman,en->button->root_coord);
-    rdman_redraw_changed(en->rdman);
-}
-static void button_out(event_t *evt, void *arg) 
-{
-    engine_t *en = (engine_t *) arg;
-
-    printf("mouse out\n");
-    COORD_HIDE(en->button->active);
-    rdman_coord_changed(en->rdman,en->button->root_coord);
-    rdman_redraw_changed(en->rdman);
-}
-
-void button_pressed(event_t *evt, void *arg)
-{
-	printf("Pressed\n");
-}
-
-void engine_add_button(engine_t *en, coord_t *normal, coord_t *active, void (*func)())
-{
-    active->matrix[2] = 200;
-    active->matrix[5] = 200;
-    normal->matrix[2] = 200;
-    normal->matrix[5] = 200;
-    COORD_HIDE(en->button->active);
-    rdman_coord_changed(en->rdman,en->button->root_coord);
-    rdman_redraw_changed(en->rdman);
-    subject_add_event_observer(CMOUSE(normal), EVT_MOUSE_MOVE, button_move,en);
-    subject_add_event_observer(CMOUSE(active), EVT_MOUSE_OUT, button_out,en);
-    subject_add_event_observer(CMOUSE(active), EVT_MOUSE_BUT_RELEASE, button_pressed,en);
-}
 
 
 void coord_move(coord_t *c, co_aix x, co_aix y)
@@ -171,17 +242,22 @@
 }
 
 
-
+void test(void *a)
+{
+    printf("Button is pressed.....\n");
+}
 
 
 int main(int argc, char * const argv[]) {
     subject_t *subject;
     engine_t *en;
+    mb_button_t *b;
 
     en = engine_init();
     en->menu = menu_new(en->rdman, en->rdman->root_coord);
     en->button = button_new(en->rdman, en->rdman->root_coord);
-    engine_add_button(en, en->button->normal, en->button->active, button_pressed);
+    b = mb_button_new(en, (mb_sprite_t *) en->button, "btn");
+    mb_button_add_onClick(b, test,NULL);
 
     en->rx = 0;
     en->ry = 0;
--- a/inkscape/AssignSymbol.py	Fri Dec 12 09:35:27 2008 +0800
+++ b/inkscape/AssignSymbol.py	Sun Dec 14 11:23:34 2008 +0800
@@ -18,6 +18,7 @@
 		text = self.text.get_text()
 		if text != self.defaultname:
 			self.node.set("mbname",text)
+			self.node.set("id",text)
 		gtk.main_quit()
 		
 	def confirm(self,msg):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inkscape/MB_EditActiveButton.py	Sun Dec 14 11:23:34 2008 +0800
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+import inkex
+import pygtk
+import gtk
+from copy import deepcopy
+
+class ConvertToButton(inkex.Effect):
+	def effect(self):
+		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+		self.window.set_position(gtk.WIN_POS_MOUSE)
+		self.defaultname = 'input symbol name here'
+		if self.fillcontent() == False:
+			self.window.show_all()
+			self.window.connect("delete_event", gtk.main_quit)
+			gtk.main()
+	def onQuit(self,data):
+		gtk.main_quit()
+	def onAssign(self,data):
+		text = self.text.get_text()
+		if text != self.defaultname:
+			self.node.set("mbname",text)
+		gtk.main_quit()
+		
+	def confirm(self,msg):
+		vbox = gtk.VBox()
+		vbox.pack_start(gtk.Label(msg))
+		self.button = gtk.Button('OK')
+		vbox.pack_start(self.button)
+		self.button.connect("clicked", self.onQuit)
+		self.window.add(vbox)
+	def dumpattr(self,n):
+		s = ""
+		for a,v in n.attrib.items():
+			s = s + ("%s=%s"  % (a,v))
+		return s
+			
+	def dump(self,node,l=0):
+		print " " * l*2,"<", node.tag, self.dumpattr(node),">"
+		for n in node:
+			self.dump(n,l+1)
+		print " " * l * 2,"/>"
+
+	def hide_frame(self,frame):
+		frame.set('style','display:none')
+	def show_frame(self,frame):
+		frame.set('style','')
+		
+
+	def fillcontent(self):
+		if len(self.selected) != 1:
+			self.confirm('Please select one group only')
+			return False
+		for id,node in self.selected.iteritems():
+			#self.dump(node)
+			name = node.get("mbname")
+			if name == None:
+				self.confirm("The MadButterFly symbol is not defined yet. Please convert it to the symbol before convert it to button.")
+				return False
+			for frame in node:
+				if frame.get('mbname') == name+'_active':
+					self.show_frame(frame)
+				else:
+					self.hide_frame(frame)
+			return True
+
+
+a=ConvertToButton()
+a.affect()
+
+# vim: set ts=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inkscape/MB_EditClickButton.py	Sun Dec 14 11:23:34 2008 +0800
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+import inkex
+import pygtk
+import gtk
+from copy import deepcopy
+
+class ConvertToButton(inkex.Effect):
+	def effect(self):
+		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+		self.window.set_position(gtk.WIN_POS_MOUSE)
+		self.defaultname = 'input symbol name here'
+		if self.fillcontent() == False:
+			self.window.show_all()
+			self.window.connect("delete_event", gtk.main_quit)
+			gtk.main()
+	def onQuit(self,data):
+		gtk.main_quit()
+	def onAssign(self,data):
+		text = self.text.get_text()
+		if text != self.defaultname:
+			self.node.set("mbname",text)
+		gtk.main_quit()
+		
+	def confirm(self,msg):
+		vbox = gtk.VBox()
+		vbox.pack_start(gtk.Label(msg))
+		self.button = gtk.Button('OK')
+		vbox.pack_start(self.button)
+		self.button.connect("clicked", self.onQuit)
+		self.window.add(vbox)
+	def dumpattr(self,n):
+		s = ""
+		for a,v in n.attrib.items():
+			s = s + ("%s=%s"  % (a,v))
+		return s
+			
+	def dump(self,node,l=0):
+		print " " * l*2,"<", node.tag, self.dumpattr(node),">"
+		for n in node:
+			self.dump(n,l+1)
+		print " " * l * 2,"/>"
+
+	def hide_frame(self,frame):
+		frame.set('style','display:none')
+	def show_frame(self,frame):
+		frame.set('style','')
+		
+
+	def fillcontent(self):
+		if len(self.selected) != 1:
+			self.confirm('Please select one group only')
+			return False
+		for id,node in self.selected.iteritems():
+			#self.dump(node)
+			name = node.get("mbname")
+			if name == None:
+				self.confirm("The MadButterFly symbol is not defined yet. Please convert it to the symbol before convert it to button.")
+				return False
+			for frame in node:
+				if frame.get('mbname') == name+'_click':
+					self.show_frame(frame)
+				else:
+					self.hide_frame(frame)
+			return True
+
+
+a=ConvertToButton()
+a.affect()
+
+# vim: set ts=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inkscape/MB_EditNormalButton.py	Sun Dec 14 11:23:34 2008 +0800
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+import inkex
+import pygtk
+import gtk
+from copy import deepcopy
+
+class ConvertToButton(inkex.Effect):
+	def effect(self):
+		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+		self.window.set_position(gtk.WIN_POS_MOUSE)
+		self.defaultname = 'input symbol name here'
+		if self.fillcontent() == False:
+			self.window.show_all()
+			self.window.connect("delete_event", gtk.main_quit)
+			gtk.main()
+	def onQuit(self,data):
+		gtk.main_quit()
+	def onAssign(self,data):
+		text = self.text.get_text()
+		if text != self.defaultname:
+			self.node.set("mbname",text)
+		gtk.main_quit()
+		
+	def confirm(self,msg):
+		vbox = gtk.VBox()
+		vbox.pack_start(gtk.Label(msg))
+		self.button = gtk.Button('OK')
+		vbox.pack_start(self.button)
+		self.button.connect("clicked", self.onQuit)
+		self.window.add(vbox)
+	def dumpattr(self,n):
+		s = ""
+		for a,v in n.attrib.items():
+			s = s + ("%s=%s"  % (a,v))
+		return s
+			
+	def dump(self,node,l=0):
+		print " " * l*2,"<", node.tag, self.dumpattr(node),">"
+		for n in node:
+			self.dump(n,l+1)
+		print " " * l * 2,"/>"
+
+	def hide_frame(self,frame):
+		frame.set('style','display:none')
+	def show_frame(self,frame):
+		frame.set('style','')
+		
+
+	def fillcontent(self):
+		if len(self.selected) != 1:
+			self.confirm('Please select one group only')
+			return False
+		for id,node in self.selected.iteritems():
+			#self.dump(node)
+			name = node.get("mbname")
+			if name == None:
+				self.confirm("The MadButterFly symbol is not defined yet. Please convert it to the symbol before convert it to button.")
+				return False
+			for frame in node:
+				if frame.get('mbname') == name+'_normal':
+					self.show_frame(frame)
+				else:
+					self.hide_frame(frame)
+			return True
+
+
+a=ConvertToButton()
+a.affect()
+
+# vim: set ts=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inkscape/MB_button_select_click.inx	Sun Dec 14 11:23:34 2008 +0800
@@ -0,0 +1,18 @@
+<inkscape-extension>
+    <name>Edit Click button</name>
+    <id>MadButterfly.EditClickButton</id>
+	<dependency type="executable" location="extensions">MB_EditClickButton.py</dependency>
+	<dependency type="executable" location="extensions">inkex.py</dependency>
+    <effect>
+		<object-type>any</object-type>
+		<effects-menu>
+			<submenu _name="MadButterfly">
+				<submenu _name="Button"/>
+			</submenu>
+		</effects-menu>
+    </effect>
+    <script>
+        <command reldir="extensions" interpreter="python">MB_EditClickButton.py</command>
+    </script>
+</inkscape-extension>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inkscape/MB_button_select_normal.inx	Sun Dec 14 11:23:34 2008 +0800
@@ -0,0 +1,18 @@
+<inkscape-extension>
+    <name>Edit Normal button</name>
+    <id>MadButterfly.EditNormalButton</id>
+	<dependency type="executable" location="extensions">MB_EditNormalButton.py</dependency>
+	<dependency type="executable" location="extensions">inkex.py</dependency>
+    <effect>
+		<object-type>any</object-type>
+		<effects-menu>
+			<submenu _name="MadButterfly">
+				<submenu _name="Button"/>
+			</submenu>
+		</effects-menu>
+    </effect>
+    <script>
+        <command reldir="extensions" interpreter="python">MB_EditNormalButton.py</command>
+    </script>
+</inkscape-extension>
+
--- a/inkscape/README.mbext	Fri Dec 12 09:35:27 2008 +0800
+++ b/inkscape/README.mbext	Sun Dec 14 11:23:34 2008 +0800
@@ -34,10 +34,13 @@
 
 <g id="g1234" mbname="btn">
     <g id="g1235" frame="active">
+    	<original object>
     </g>
     <g id="g1235" frame="normal">
+    	<original object>
     </g>
     <g id="g1236" frame="click">
+    	<original object>
     </g>
 </g>
 
--- a/tools/mb_c_source.m4	Fri Dec 12 09:35:27 2008 +0800
+++ b/tools/mb_c_source.m4	Sun Dec 14 11:23:34 2008 +0800
@@ -355,9 +355,6 @@
 
 #ifndef MB_LSYM_GET_OBJ_WITH_NAME
 #define MB_LSYM_GET_OBJ_WITH_NAME
-
-#define MB_SPRITE_OFF_2_PTR(x, off) (((void *)(x)) + (off))
-
 static
 mb_obj_t *mb_lsym_get_obj_with_name(mb_sprite_lsym_t *lsym, const char *sym) {
     int i;
@@ -365,8 +362,7 @@
     for(i = 0; i < lsym->num_entries; i++) {
 	if(strcmp(lsym->entries[i].sym, sym) != 0)
 	    continue;
-	return *(mb_obj_t **)MB_SPRITE_OFF_2_PTR(lsym,
-					         lsym->entries[i].offset);
+	return (mb_obj_t *)*((int*)(((void *)lsym) + lsym->entries[i].offset));
     }
     return NULL;
 }