Attached are my first draft for annotate to add the
guiding lines.

I have added them for line, circle and rectangle
so far.

I have also added an action to quickly change the tool.

I have some questions about them.

1) I used an enum for the tool type but if it is
changed by the tool_next action then it does not 
update in the settings, Is there an easy way to
do this other than a couple of conversion functions?
Does this look like the best way to avoid all the
sring comparisons?

2) It seems like adding text with cairo/opengl would
lead to lots of headaches, limitations and bloat.
My idea is that a seperate helper app could be written
which could provide a palette as well as text entering
functionality.  I could add an extra action to launch 
it, and it could launch the app via dbus to enter text.
Does this sound like a good idea?

3) In the annoHandleMotionEvent I have added a
damageScreen call.  I suspect this should be
damageScreenRegion but in the case of the rectangle
is there much benefit in damaging 4 small rectangles 
rather than the whole thing?

I still need to add onscreen feedback when the tool
changes and I want to add SVG and different line 
endings and tidy things up a bit.  Does everything 
look OK so far?

Regards
Mike

--- plugins/annotate.c.orig     2006-12-12 18:39:09.046115408 +0000
+++ plugins/annotate.c  2007-01-02 17:14:58.799983264 +0000
@@ -36,6 +36,12 @@
 #define ANNO_ERASE_BUTTON_DEFAULT          Button3
 #define ANNO_ERASE_BUTTON_MODIFIERS_DEFAULT (CompSuperMask | CompAltMask)
 
+#define ANNO_PREV_TOOL_BUTTON_DEFAULT      Button4
+#define ANNO_PREV_TOOL_BUTTON_MODIFIERS_DEFAULT (CompSuperMask | CompAltMask)
+
+#define ANNO_NEXT_TOOL_BUTTON_DEFAULT      Button5
+#define ANNO_NEXT_TOOL_BUTTON_MODIFIERS_DEFAULT (CompSuperMask | CompAltMask)
+
 #define ANNO_CLEAR_KEY_DEFAULT          "k"
 #define ANNO_CLEAR_KEY_MODIFIERS_DEFAULT (CompSuperMask | CompAltMask)
 
@@ -70,13 +76,26 @@
 #define ANNO_DISPLAY_OPTION_STROKE_COLOR 5
 #define ANNO_DISPLAY_OPTION_LINE_WIDTH   6
 #define ANNO_DISPLAY_OPTION_STROKE_WIDTH 7
-#define ANNO_DISPLAY_OPTION_NUM                 8
+#define ANNO_DISPLAY_OPTION_TOOL         8
+#define ANNO_DISPLAY_OPTION_TOOL_PREV    9
+#define ANNO_DISPLAY_OPTION_TOOL_NEXT    10
+#define ANNO_DISPLAY_OPTION_NUM                 11
+
+typedef enum {
+    AnnoToolBrush,
+    AnnoToolLine,
+    AnnoToolRectangle,
+    AnnoToolCircle,
+    AnnoToolNull
+} AnnoTool;
 
 typedef struct _AnnoDisplay {
     int                    screenPrivateIndex;
     HandleEventProc handleEvent;
 
     CompOption opt[ANNO_DISPLAY_OPTION_NUM];
+
+    AnnoTool currentTool;
 } AnnoDisplay;
 
 typedef struct _AnnoScreen {
@@ -90,6 +109,8 @@
     Bool            content;
 
     Bool eraseMode;
+
+    int x1, y1;
 } AnnoScreen;
 
 #define GET_ANNO_DISPLAY(d)                                 \
@@ -109,6 +130,11 @@
 
 #define NUM_TOOLS (sizeof (tools) / sizeof (tools[0]))
 
+#define DELTA(x, y) (MAX(x, y) - MIN(x, y))
+
+#define CIRCLE_RADIUS(x1, x2, y1, y2)                                          
\
+       (int) sqrt(pow(DELTA(x1, x2), 2) + pow(DELTA(y1, y2), 2))
+
 static void
 annoCairoClear (CompScreen *s,
                cairo_t    *cr)
@@ -494,8 +520,8 @@
        if (state & CompActionStateInitKey)
            action->state |= CompActionStateTermKey;
 
-       annoLastPointerX = pointerX;
-       annoLastPointerY = pointerY;
+       as->x1 = annoLastPointerX = pointerX;
+       as->y1 = annoLastPointerY = pointerY;
 
        as->eraseMode = FALSE;
     }
@@ -513,15 +539,50 @@
     CompScreen *s;
     Window     xid;
 
+    ANNO_DISPLAY(d);
+
     xid = getIntOptionNamed (option, nOption, "root", 0);
 
     for (s = d->screens; s; s = s->next)
     {
-       ANNO_SCREEN (s);
-
        if (xid && s->root != xid)
            continue;
 
+       ANNO_SCREEN (s);
+
+        switch (ad->currentTool)
+        {
+       case AnnoToolLine:
+           annoDrawLine (s,
+                         as->x1, as->y1,
+                         pointerX, pointerY,
+                         ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f,
+                         ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c);
+           break;
+       case AnnoToolRectangle:{
+           int x, y, h, w;
+           x = MIN (as->x1, pointerX);
+           y = MIN (as->y1, pointerY);
+           w = DELTA (as->x1, pointerX);
+           h = DELTA (as->y1, pointerY);
+           annoDrawRectangle (s, x, y, w, h,
+                              ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c,
+                              
ad->opt[ANNO_DISPLAY_OPTION_STROKE_COLOR].value.c,
+                              ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f);
+       }
+           break;
+       case AnnoToolCircle:{
+           int r = CIRCLE_RADIUS (as->x1, pointerX, as->y1, pointerY);
+
+           annoDrawCircle (s, as->x1, as->y1, r,
+                             ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c,
+                             ad->opt[ANNO_DISPLAY_OPTION_STROKE_COLOR].value.c,
+                             ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f);
+       }
+       default:
+           break;
+        }
+
        if (as->grabIndex)
        {
            removeScreenGrab (s, as->grabIndex, NULL);
@@ -607,6 +668,41 @@
 }
 
 static Bool
+annoToolPrev (CompDisplay     *d,
+             CompAction      *action,
+             CompActionState state,
+             CompOption      *option,
+             int             nOption)
+{
+       ANNO_DISPLAY (d);
+
+       ad->currentTool++;
+
+       if (ad->currentTool == AnnoToolNull)
+           ad->currentTool = 0;
+
+       return TRUE;
+
+}
+
+static Bool
+annoToolNext (CompDisplay     *d,
+             CompAction      *action,
+             CompActionState state,
+             CompOption      *option,
+             int             nOption)
+{
+       ANNO_DISPLAY (d);
+
+       if (ad->currentTool == 0)
+           ad->currentTool = AnnoToolNull;
+
+       ad->currentTool--;
+
+       return TRUE;
+}
+
+static Bool
 annoPaintScreen (CompScreen             *s,
                 const ScreenPaintAttrib *sAttrib,
                 Region                  region,
@@ -616,6 +712,7 @@
     Bool status;
 
     ANNO_SCREEN (s);
+    ANNO_DISPLAY (s->display);
 
     UNWRAP (as, s, paintScreen);
     status = (*s->paintScreen) (s, sAttrib, region, output, mask);
@@ -668,6 +765,58 @@
        glPopMatrix ();
     }
 
+    /* draw the guiding lines */
+    if (status && as->grabIndex)
+    {
+       glPushMatrix ();
+
+       prepareXCoords (s, output, -DEFAULT_Z_CAMERA);
+
+       glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+       glEnable (GL_BLEND);
+       glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
+
+       switch (ad->currentTool)
+       {
+           case AnnoToolLine:
+               glBegin(GL_LINES);
+               glVertex2i(as->x1, as->y1);
+               glVertex2i(pointerX, pointerY);
+               glEnd ();
+           break;
+           case AnnoToolRectangle:
+               glBegin(GL_LINE_LOOP);
+               glVertex2i(as->x1, as->y1);
+               glVertex2i(pointerX, as->y1);
+               glVertex2i(pointerX, pointerY);
+               glVertex2i(as->x1, pointerY);
+               glEnd ();
+           break;
+           case AnnoToolCircle:{
+               int radius;
+               float agl;
+
+               radius = CIRCLE_RADIUS (as->x1, pointerX, as->y1, pointerY);
+
+               glBegin(GL_LINE_LOOP);
+               for (agl=0.0f;agl<(2.0f*3.1415927f);agl+=0.1f)
+                   glVertex2i((int) (cos(agl)*radius) + as->x1,
+                              (int) (sin(agl)*radius) + as->y1);
+               glEnd ();
+           }
+           default:
+
+       break;
+       }
+
+       glColor4usv(defaultColor);
+
+       glDisable (GL_BLEND);
+       glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+       glPopMatrix ();
+    }
+
     return status;
 }
 
@@ -677,6 +826,7 @@
                       int        yRoot)
 {
     ANNO_SCREEN (s);
+    ANNO_DISPLAY (s->display);
 
     if (as->grabIndex)
     {
@@ -689,7 +839,7 @@
                          xRoot, yRoot,
                          20.0, color);
        }
-       else
+       else if (ad->currentTool == AnnoToolBrush)
        {
            ANNO_DISPLAY(s->display);
 
@@ -699,6 +849,10 @@
                          ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f,
                          ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c);
        }
+       else
+       {
+           damageScreen(s);
+       }
 
        annoLastPointerX = xRoot;
        annoLastPointerY = yRoot;
@@ -838,6 +992,46 @@
     o->rest.f.min       = ANNO_STROKE_WIDTH_MIN;
     o->rest.f.max       = ANNO_STROKE_WIDTH_MAX;
     o->rest.f.precision = ANNO_STROKE_WIDTH_PRECISION;
+
+    o = &ad->opt[ANNO_DISPLAY_OPTION_TOOL];
+    o->name             = "tool";
+    o->shortDesc        = N_("The current tool");
+    o->longDesc         = N_("The current tool to use (Brush, Rectangle," \
+                            " Line or Circle)");
+    o->type             = CompOptionTypeString;
+    o->value.s          = strdup("");
+    o->rest.s.string    = 0;
+    o->rest.s.nString   = 0;
+
+    o = &ad->opt[ANNO_DISPLAY_OPTION_TOOL_PREV];
+    o->name                         = "tool_prev";
+    o->shortDesc                    = N_("Select the previous tool");
+    o->longDesc                             = N_("Select the previous tool");
+    o->type                         = CompOptionTypeAction;
+    o->value.action.initiate        = annoToolPrev;
+    o->value.action.terminate       = 0;
+    o->value.action.bell            = FALSE;
+    o->value.action.edgeMask        = 0;
+    o->value.action.type            = CompBindingTypeButton;
+    o->value.action.state           = CompActionStateInitButton;
+    o->value.action.state          |= CompActionStateInitKey;
+    o->value.action.button.modifiers = ANNO_PREV_TOOL_BUTTON_MODIFIERS_DEFAULT;
+    o->value.action.button.button    = ANNO_PREV_TOOL_BUTTON_DEFAULT;
+
+    o = &ad->opt[ANNO_DISPLAY_OPTION_TOOL_NEXT];
+    o->name                         = "tool_next";
+    o->shortDesc                    = N_("Select the next tool");
+    o->longDesc                             = N_("Select the next tool");
+    o->type                         = CompOptionTypeAction;
+    o->value.action.initiate        = annoToolNext;
+    o->value.action.terminate       = 0;
+    o->value.action.bell            = FALSE;
+    o->value.action.edgeMask        = 0;
+    o->value.action.type            = CompBindingTypeButton;
+    o->value.action.state           = CompActionStateInitButton;
+    o->value.action.state          |= CompActionStateInitKey;
+    o->value.action.button.modifiers = ANNO_NEXT_TOOL_BUTTON_MODIFIERS_DEFAULT;
+    o->value.action.button.button    = ANNO_NEXT_TOOL_BUTTON_DEFAULT;
 }
 
 static CompOption *
@@ -868,6 +1062,8 @@
     case ANNO_DISPLAY_OPTION_INITIATE:
     case ANNO_DISPLAY_OPTION_ERASE:
     case ANNO_DISPLAY_OPTION_CLEAR:
+    case ANNO_DISPLAY_OPTION_TOOL_PREV:
+    case ANNO_DISPLAY_OPTION_TOOL_NEXT:
        if (setDisplayAction (display, o, value))
            return TRUE;
        break;
@@ -880,6 +1076,20 @@
     case ANNO_DISPLAY_OPTION_STROKE_WIDTH:
        if (compSetFloatOption (o, value))
            return TRUE;
+       break;
+    case ANNO_DISPLAY_OPTION_TOOL:
+       if (compSetStringOption (o, value))
+       {
+           if (strcmp(value->s, "Line") == 0)
+               ad->currentTool = AnnoToolLine;
+           else if (strcmp(value->s, "Rectangle") == 0)
+               ad->currentTool = AnnoToolRectangle;
+           else if (strcmp(value->s, "Circle") == 0)
+               ad->currentTool = AnnoToolCircle;
+           else
+               ad->currentTool = AnnoToolBrush;
+           return TRUE;
+       }
     default:
        break;
     }
_______________________________________________
compiz mailing list
compiz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/compiz

Reply via email to