Browse Source

Libjay init (#805)

Starting libjay

Signed-off-by: fuchicar <rafita.fernandez@gmail.com>
Rafa 6 years ago
parent
commit
c5921efaeb

+ 129 - 0
sys/include/jay.h

@@ -0,0 +1,129 @@
+
+typedef struct Jayconfig Jayconfig;
+typedef struct Widget Widget;
+typedef struct WListElement WListElement;
+typedef struct Panel Panel;
+typedef struct Label Label;
+typedef enum wtype wtype;
+
+enum wtype{
+  PANEL,
+  LABEL
+};
+
+struct Jayconfig{
+	// Task Panel Config
+	uint32_t taskPanelColor;
+
+	// Main Menu Config
+	uint32_t mainMenuColor;
+	uint32_t mainMenuHooverColor;
+
+	// Window Config
+	uint32_t windowTitleColor;
+	uint32_t windowTitleFontColor;
+	uint32_t windowBackgroundColor;
+	uint32_t windowInTopBorder;
+	uint32_t windowInBottomBorder;
+	uint32_t windowSelectedColor;
+	uint32_t windowScrollBarFrontColor;
+	uint32_t windowTextCursorColor;
+	uint32_t windowBackTextColor;
+	uint32_t windowFrontTextColor;
+
+	//Background
+	uint32_t backgroundColor;
+	char *backgroundimgpath;
+
+	//Menu
+	uint32_t menuBackColor;
+	uint32_t menuHighColor;
+	uint32_t menuBorderColor;
+	uint32_t menuTextColor;
+	uint32_t menuSelTextColor;
+
+  //Widgets
+  uint32_t mainBackColor;
+  uint32_t mainTextColor;
+  char *fontPath;
+
+  unsigned int doubleclickTime;
+};
+
+struct Widget {
+  char *id;
+
+  //Methods
+  int (*addWidget)(Widget *me, Widget *new, Point pos);
+  void (*setVisible)(Widget *w, int visible);
+
+  //User Events:
+  void (*hover)(Widget *w);
+  void (*unhover)(Widget *w);
+  void (*draw)(Widget *w);
+  void (*resize)(Widget *w);
+  void (*click)(Widget *w, Mouse *);
+  void (*dclick)(Widget *w, Mouse *);
+  void (*mpressdown)(Widget *w, Mouse *);
+  void (*mpressup)(Widget *w, Mouse *);
+  void (*change)(Widget *w);
+
+  //For internal use
+  void (*_hover)(Widget *w, Mouse *m);
+  void (*_unhover)(Widget *w);
+  void (*_draw)(Widget *w, Image *dst);
+  void (*_redraw)(Widget *w);
+  void (*_resize)(Widget *w, Point d); //d is the vector that represents the displacement
+  void (*_click)(Widget *w, Mouse *);
+  void (*_dclick)(Widget *w, Mouse *);
+  void (*_mpressdown)(Widget *w, Mouse *);
+  void (*_mpressup)(Widget *w, Mouse *);
+  void (*_change)(Widget *w);
+
+  int width; //ancho
+  int height;//alto
+  int hovered;
+  int autosize;
+  Rectangle r;
+  Point p; //Real position
+  Point pos; //Relative position
+  wtype t; //widget type
+  void *w; //The widget
+  Widget *father; //Container
+  Image *i;
+  int visible;
+  Widget *lh; //last hover
+};
+
+struct WListElement {
+  WListElement *next;
+  WListElement *prev;
+  Widget *w;
+};
+
+struct Panel {
+  Widget *w;
+  uint32_t backColor;
+  WListElement *l;
+};
+
+struct Label {
+  Widget *w;
+  char *t;
+  Font *f;
+
+  int border;
+  int d3; // 3D Border true/false
+  int up; // If d3=true then up defines the efect
+  uint32_t backColor;
+  uint32_t textColor;
+
+  void (*setText)(Label *l, const char *text);
+  char * (*gettext)(Label *l);
+};
+
+Widget *initjayapp(char *name);
+void startjayapp(Widget * w);
+void initdefaultconfig();
+Widget *createPanel(char *id, int height, int width, Point p);
+Widget *createLabel(char *id, int height, int width);

+ 1 - 0
sys/src/cmd/cmd.json

@@ -9,6 +9,7 @@
 			"-lavl",
 			"-lcomplete",
 			"-lcontrol",
+			"-ljay",
 			"-ldisk",
 			"-lflate",
 			"-lframe",

+ 1 - 29
sys/src/cmd/jay/config.c

@@ -7,38 +7,10 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 
-void
-initdefaultconfig(){
-	jayconfig = malloc(sizeof(Jayconfig));
-	jayconfig->taskPanelColor = 0x8C7160FF;
-
-	jayconfig->mainMenuColor = 0x363533FF;
-	jayconfig->mainMenuHooverColor = 0x36A4BFFF;
-
-	jayconfig->windowTitleColor = 0x4D4D4DFF;
-	jayconfig->windowTitleFontColor = DWhite;
-	jayconfig->windowInTopBorder = 0xC4CAC8FF;
-	jayconfig->windowInBottomBorder = DPalegreygreen;
-	jayconfig->windowSelectedColor = 0xCCCCCCFF;
-	jayconfig->windowScrollBarFrontColor = DWhite;//0x999999FF;
-	jayconfig->windowTextCursorColor = DWhite;
-	jayconfig->windowBackgroundColor = DBlack;
-	jayconfig->windowBackTextColor = 0x666666FF;
-	jayconfig->windowFrontTextColor = DWhite;
-
-	jayconfig->backgroundColor = DBlack;
-	jayconfig->backgroundimgpath = "/usr/harvey/lib/background.img";
-
-	jayconfig->menuBackColor = DPalegreyblue;
-	jayconfig->menuHighColor = DGreyblue;
-	jayconfig->menuBorderColor = jayconfig->menuHighColor;
-	jayconfig->menuSelTextColor = DWhite;
-	jayconfig->menuTextColor = DWhite;
-}
-
 char *
 getjayconfig(){
   char s[1024];

+ 0 - 34
sys/src/cmd/jay/dat.h

@@ -57,7 +57,6 @@ typedef	struct	Xfid Xfid;
 typedef	struct TPanel TPanel;
 typedef struct MenuEntry MenuEntry;
 typedef struct StartMenu StartMenu;
-typedef struct Jayconfig Jayconfig;
 
 enum
 {
@@ -224,38 +223,6 @@ struct Window
 	int maximized;
 };
 
-struct Jayconfig{
-	// Task Panel Config
-	uint32_t taskPanelColor;
-
-	// Main Menu Config
-	uint32_t mainMenuColor;
-	uint32_t mainMenuHooverColor;
-
-	// Window Config
-	uint32_t windowTitleColor;
-	uint32_t windowTitleFontColor;
-	uint32_t windowBackgroundColor;
-	uint32_t windowInTopBorder;
-	uint32_t windowInBottomBorder;
-	uint32_t windowSelectedColor;
-	uint32_t windowScrollBarFrontColor;
-	uint32_t windowTextCursorColor;
-	uint32_t windowBackTextColor;
-	uint32_t windowFrontTextColor;
-
-	//Background
-	uint32_t backgroundColor;
-	char *backgroundimgpath;
-
-	//Menu
-	uint32_t  menuBackColor;
-	uint32_t menuHighColor;
-	uint32_t menuBorderColor;
-	uint32_t menuTextColor;
-	uint32_t menuSelTextColor;
-};
-
 int		winborder(Window*, Point);
 Image *winspace(Window *w);
 void		winctl(void*);
@@ -455,7 +422,6 @@ Image *wht;
 //Config
 Jayconfig *jayconfig;
 
-void initdefaultconfig();
 char *getjayconfig();
 void setjayconfig(char *conf);
 void jayredraw(void);

+ 1 - 0
sys/src/cmd/jay/data.c

@@ -16,6 +16,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/fsys.c

@@ -16,6 +16,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/jay.c

@@ -17,6 +17,7 @@
 #include <frame.h>
 #include <fcall.h>
 #include <plumb.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/panel.c

@@ -7,6 +7,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/scrl.c

@@ -16,6 +16,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/smenu.c

@@ -7,6 +7,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/time.c

@@ -16,6 +16,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/util.c

@@ -16,6 +16,7 @@
 #include <keyboard.h>
 #include <frame.h>
 #include <fcall.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/wctl.c

@@ -17,6 +17,7 @@
 #include <frame.h>
 #include <fcall.h>
 #include <plumb.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 #include <ctype.h>

+ 1 - 0
sys/src/cmd/jay/wind.c

@@ -18,6 +18,7 @@
 #include <fcall.h>
 #include <plumb.h>
 #include <complete.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 1 - 0
sys/src/cmd/jay/xfid.c

@@ -17,6 +17,7 @@
 #include <frame.h>
 #include <fcall.h>
 #include <plumb.h>
+#include <jay.h>
 #include "dat.h"
 #include "fns.h"
 

+ 42 - 0
sys/src/libjay/config.c

@@ -0,0 +1,42 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void
+initdefaultconfig(){
+	jayconfig = malloc(sizeof(Jayconfig));
+	jayconfig->taskPanelColor = 0x8C7160FF;
+
+	jayconfig->mainMenuColor = 0x363533FF;
+	jayconfig->mainMenuHooverColor = 0x36A4BFFF;
+
+	jayconfig->windowTitleColor = 0x4D4D4DFF;
+	jayconfig->windowTitleFontColor = DWhite;
+	jayconfig->windowInTopBorder = 0xC4CAC8FF;
+	jayconfig->windowInBottomBorder = DPalegreygreen;
+	jayconfig->windowSelectedColor = 0xCCCCCCFF;
+	jayconfig->windowScrollBarFrontColor = DWhite;
+	jayconfig->windowTextCursorColor = DWhite;
+	jayconfig->windowBackgroundColor = DBlack;
+	jayconfig->windowBackTextColor = 0x666666FF;
+	jayconfig->windowFrontTextColor = DWhite;
+
+	jayconfig->backgroundColor = DBlack;
+	jayconfig->backgroundimgpath = "/usr/harvey/lib/background.img";
+
+	jayconfig->menuBackColor = DPalegreyblue;
+	jayconfig->menuHighColor = DGreyblue;
+	jayconfig->menuBorderColor = jayconfig->menuHighColor;
+	jayconfig->menuSelTextColor = DWhite;
+	jayconfig->menuTextColor = DWhite;
+
+	jayconfig->mainBackColor = DWhite;
+	jayconfig->mainTextColor = DBlack;
+
+	jayconfig->fontPath = "/lib/font/bit/go/Go-Mono/Go-Mono.14.font";
+	jayconfig->doubleclickTime = 500;
+}

+ 10 - 0
sys/src/libjay/fns.h

@@ -0,0 +1,10 @@
+Jayconfig *jayconfig;
+
+Widget *createWidget(char *id, int height, int width, wtype t, void *w);
+Widget *createWidget1(char *id, Rectangle r, wtype t, void *w);
+Widget *createPanel1(char *id, Rectangle r, Point p);
+WListElement *createWListElement(Widget *w);
+WListElement *getWListElementByID(WListElement *list, char *id);
+int addWListElement(WListElement *list, Widget *w);
+
+void _simpleResize(Widget *w, Point d);

+ 262 - 0
sys/src/libjay/label.c

@@ -0,0 +1,262 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void _hoverLabel(Widget *w, Mouse *m);
+void _unhoverLabel(Widget *w);
+void _drawLabel(Widget *w, Image *dst);
+void _redrawLabel(Widget *w);
+void _setTextLabel(Label *l, const char *t);
+char *_getTextLabel(Label *l);
+static Rectangle autosizeLabel(Widget *w);
+void _clickLabel(Widget *w, Mouse *m);
+void _dclickLabel(Widget *w, Mouse *m);
+void _mPressDownLabel(Widget *w, Mouse *m);
+void _mPressUpLabel(Widget *w, Mouse *m);
+void _changeLabel(Widget *w);
+
+Widget *
+createLabel(char *id, int height, int width){
+  Label *laux = malloc(sizeof(Label));
+  if (laux == nil){
+    return nil;
+  }
+  Widget *w = createWidget(id, height, width, LABEL, laux);
+  if (w == nil){
+    return nil;
+  }
+  laux->f = openfont(display, jayconfig->fontPath);
+  if (laux->f == nil){
+    return nil;
+  }
+  laux->t = nil;
+  laux->backColor = jayconfig->mainBackColor;
+  laux->textColor = jayconfig->mainTextColor;
+  laux->border = 0;
+  laux->d3 = 0;
+  laux->up = 0;
+  laux->w = w;
+  laux->gettext=_getTextLabel;
+  laux->setText=_setTextLabel;
+  w->_hover = _hoverLabel;
+  w->_unhover = _unhoverLabel;
+  w->_draw=_drawLabel;
+  w->_redraw=_redrawLabel;
+  w->_resize=_simpleResize;
+  w->_click=_clickLabel;
+  w->_dclick=_dclickLabel;
+  w->_mpressdown=_mPressDownLabel;
+  w->_mpressup=_mPressUpLabel;
+  w->_change=_changeLabel;
+  return w;
+}
+
+static int
+checkLabel(Widget *w){
+  if (w == nil || w->t != LABEL || w->w == nil){
+    return 0;
+  }
+  return 1;
+}
+
+void
+_hoverLabel(Widget *w, Mouse *m){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  w->hovered=1;
+  if( w->hover != nil){
+    w->hover(w);
+    w->_redraw(w);
+  }
+}
+
+void
+_unhoverLabel(Widget *w){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  w->hovered = 0;
+  if (w->unhover != nil){
+    w->unhover(w);
+    w->_redraw(w);
+  }
+}
+
+void
+_drawLabel(Widget *w, Image *dst){
+  if(!checkLabel(w) || w->father == nil || !w->visible || !w->father->visible){
+    return;
+  }
+
+  Label *l = w->w;
+
+  if(w->i != nil){
+    freeimage(w->i);
+  }
+  if (w->height == 0 || w->width == 0){
+    return;
+  }
+  if(w->height<0 || w->width<0){
+    w->r = autosizeLabel(w);
+  }
+  w->i = allocimage(display, w->r, RGB24, 1, l->backColor);
+  if (w->i == nil){
+    sysfatal("_drawLabel: %r");
+  }
+
+  if(l->t != nil){
+    Image *i = allocimage(display, Rect(0,0,1,1), RGB24, 1, l->textColor);
+    Rectangle r = insetrect(w->r, l->border);
+    Point s = stringsize(l->f, l->t);
+    Point p = Pt(r.min.x, r.min.y + ((Dy(r)/2) - (s.y/2) + 1) );
+    string(w->i, p, i, p, l->f, l->t);
+    freeimage(i);
+  }
+
+  if (l->border > 0){
+    if (l->d3){
+      Image *i=allocimage(display, Rect(0,0,1,1), RGB24, 1, 0xCCCCCCFF);
+      if(l->up){
+        border3d(w->i, w->r, l->border, i, display->black, ZP);
+      } else {
+        border3d(w->i, w->r, l->border, display->black, i, ZP);
+      }
+      freeimage(i);
+    } else {
+      border(w->i, w->r, l->border, display->black, ZP);
+    }
+  }
+  draw(dst, w->r, w->i, nil, w->p);
+  if(w->draw != nil){
+    w->draw(w);
+  }
+  flushimage(display, 1);
+}
+
+void
+_redrawLabel(Widget *w){
+  if(!checkLabel(w) || w->father == nil || !w->visible || !w->father->visible){
+    return;
+  }
+  if (w->autosize){
+    Rectangle r = autosizeLabel(w);
+    if(!eqrect(r, w->r)){
+      // The geometry has changed, so we need to redraw all
+      w->father->_redraw(w->father);
+    }
+  }
+  w->_draw(w, screen);
+}
+
+void
+_setTextLabel(Label *l, const char *t){
+  if (l->t != nil){
+    if(strcmp(l->t, t) == 0){
+      // If the text is equal, do nothing
+      return;
+    }
+    free(l->t);
+  }
+  l->t=strdup(t);
+  l->w->_change(l->w);
+  l->w->_redraw(l->w);
+}
+
+char *
+_getTextLabel(Label *l){
+  return strdup(l->t);
+}
+
+static Rectangle
+autosizeLabel(Widget *w){
+  int fh, fw; //Final heigh, final width
+  if(!checkLabel(w)){
+    return ZR;
+  }
+  Label *l = w->w;
+
+  fh = w->height;
+  fw = w->width;
+  if (l->t == nil || strcmp("", l->t) == 0){
+    if (fh<0){
+      fh=20;
+    }
+    if (fw<0){
+      fw=12;
+    }
+  } else {
+    Point p = stringsize(l->f, l->t);
+    if (fh<0){
+      fh = p.y + (2*l->border); //2*border because is a box, we have 2 sides in this axis.
+    }
+    if(fw<0){
+      fw = p.x + (2*l->border); //2*border because is a box, we have 2 sides in this axis.
+    }
+  }
+  return Rect(w->p.x, w->p.y, w->p.x + fw, w->p.y + fh);
+}
+
+void
+_clickLabel(Widget *w, Mouse *m){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  if(w->click != nil){
+    w->click(w, m);
+    w->_redraw(w);
+  }
+}
+
+void
+_dclickLabel(Widget *w, Mouse *m){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  if(w->dclick != nil){
+    w->dclick(w, m);
+    w->_redraw(w);
+  }
+}
+
+void
+_mPressDownLabel(Widget *w, Mouse *m){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  if(w->mpressdown != nil){
+    w->mpressdown(w, m);
+    w->_redraw(w);
+  }
+}
+
+void
+_mPressUpLabel(Widget *w, Mouse *m){
+  if(!checkLabel(w)){
+    return;
+  }
+
+  if(w->mpressup != nil){
+    w->mpressup(w, m);
+    w->_redraw(w);
+  }
+}
+
+void
+_changeLabel(Widget *w){
+  if(!checkLabel(w)){
+    return;
+  }
+  if (w->change != nil){
+    w->change(w);
+  }
+}

+ 18 - 0
sys/src/libjay/libjay.json

@@ -0,0 +1,18 @@
+{
+	"libcontrol": {
+		"Include": [
+			"../lib.json"
+		],
+		"Install": "/$ARCH/lib/",
+		"Library": "libjay.a",
+		"SourceFiles": [
+			"config.c",
+			"label.c",
+			"panel.c",
+			"utils.c",
+			"widget.c",
+			"window.c",
+			"wlist.c"
+		]
+	}
+}

+ 278 - 0
sys/src/libjay/panel.c

@@ -0,0 +1,278 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void _hoverPanel(Widget *w, Mouse *m);
+void _unhoverPanel(Widget *w);
+void _drawPanel(Widget *w, Image *dst);
+void _redrawPanel(Widget *w);
+int _addWidgetToPanel(Widget *me, Widget *new, Point pos);
+void _resizePanel(Widget *w, Point d);
+void _clickPanel(Widget *w, Mouse *m);
+void _dclickPanel(Widget *w, Mouse *m);
+void _mPressDownPanel(Widget *w, Mouse *m);
+void _mPressUpPanel(Widget *w, Mouse *m);
+
+static void
+genPanel(Widget *w, Panel *paux, Point p){
+  paux->w=w;
+  paux->l = nil;
+  paux->backColor = jayconfig->mainBackColor;
+  w->_hover=_hoverPanel;
+  w->_unhover=_unhoverPanel;
+  w->_draw=_drawPanel;
+  w->_redraw=_redrawPanel;
+  w->addWidget=_addWidgetToPanel;
+  w->_resize=_resizePanel;
+  w->_click=_clickPanel;
+  w->_dclick=_dclickPanel;
+  w->_mpressdown=_mPressDownPanel;
+  w->_mpressup=_mPressUpPanel;
+  w->p=p;
+}
+
+Widget *
+createPanel1(char *id, Rectangle r, Point p){
+  Panel *paux = malloc(sizeof(Panel));
+  if (paux == nil){
+    return nil;
+  }
+  Widget *w = createWidget1(id, r, PANEL, paux);
+  if (w == nil){
+    return nil;
+  }
+  genPanel(w, paux, p);
+  return w;
+}
+
+Widget *
+createPanel(char *id, int height, int width, Point p){
+  Panel *paux = malloc(sizeof(Panel));
+  if (paux == nil){
+    return nil;
+  }
+  Widget *w = createWidget(id, height, width, PANEL, paux);
+  if (w == nil){
+    return nil;
+  }
+  genPanel(w, paux, p);
+  return w;
+}
+
+static int
+checkPanel(Widget *w){
+  if (w == nil || w->t != PANEL || w->w == nil || !w->visible){
+    return 0;
+  }
+  return 1;
+}
+
+void
+_hoverPanel(Widget *w, Mouse *m){
+  if(!checkPanel(w)){
+    return;
+  }
+  Panel *p = (Panel *)w->w;
+  w->hovered=1;
+  if(w->lh != nil){
+    if(ptinrect(m->xy, w->lh->r)){
+      if(w->lh->t == PANEL){
+        //It's a container, so we need to send again the _hover event
+        w->lh->_hover(w->lh, m);
+      }
+      return;
+    }
+    w->lh->_unhover(w->lh);
+    w->lh=nil;
+  }
+  for (WListElement *i=p->l; i != nil; i=i->next){
+    if(ptinrect(m->xy, i->w->r)){
+      if (!i->w->hovered){
+        i->w->_hover(i->w, m);
+        w->lh = i->w;
+        return;
+      }
+    }
+  }
+  if(w->hover!=nil){
+    w->hover(w);
+    w->_redraw(w);
+  }
+}
+
+void
+_unhoverPanel(Widget *w){
+  if(!checkPanel(w)){
+    return;
+  }
+  w->hovered = 0;
+  if (w->unhover != nil){
+    w->unhover(w);
+    w->_redraw(w);
+  }
+}
+
+void
+_drawPanel(Widget *w, Image *dst) {
+  if(!checkPanel(w)){
+    return;
+  }
+  Panel *p = (Panel *)w->w;
+
+  if (w->i != nil){
+    freeimage(w->i);
+  }
+  w->i = allocimage(display, w->r, RGB24, 1, p->backColor);
+  if(w->i == nil){
+    sysfatal("_drawPanel: %r");
+  }
+
+  for (WListElement *e=p->l; e != nil; e=e->next){
+    if(e->w->visible){
+      e->w->_draw(e->w, w->i);
+    }
+  }
+  draw(dst, w->r, w->i, nil, w->p);
+  flushimage(display, 1);
+}
+
+int
+_addWidgetToPanel(Widget *me, Widget *new, Point pos){
+  Point real;
+  if (me == nil || me->t != PANEL || me->w == nil){
+    return 0;
+  }
+  Panel *p = (Panel *)me->w;
+
+  real.x = me->r.min.x + pos.x;
+  real.y = me->r.min.y + pos.y;
+  new->p = real;
+  new->pos = pos;
+  if (!new->autosize){
+    new->r = Rect(real.x, real.y, real.x + new->width, real.y + new->height);
+  }
+  if(p->l == nil){
+    p->l = createWListElement(new);
+    if (p->l == nil){
+      return 0;
+    }
+  } else if (!addWListElement(p->l, new)) {
+    return 0;
+  }
+  new->father = me;
+  return 1;
+}
+
+void
+_redrawPanel(Widget *w){
+  if(!checkPanel(w)){
+    return;
+  }
+  if(w->father==nil || !w->autosize){
+    w->_draw(w, screen);
+  } else {
+    w->father->_redraw(w->father);
+  }
+}
+
+void
+_resizePanel(Widget *w, Point d){
+  if(!checkPanel(w)){
+    return;
+  }
+  Panel *p = (Panel *)w->w;
+
+  _simpleResize(w, d);
+  for (WListElement *e=p->l; e != nil; e=e->next){
+    e->w->_resize(e->w, d);
+  }
+  if(w->father == nil){
+    //I'm the main panel
+    w->_draw(w, screen);
+  }
+  flushimage(display, 1);
+}
+
+void
+_clickPanel(Widget *w, Mouse *m){
+  if(!checkPanel(w)){
+    return;
+  }
+
+  w->_hover(w, m);
+
+  if (w->lh == nil){
+    //Click on the panel
+    if(w->click != nil){
+      w->click(w, m);
+      w->_redraw(w);
+    }
+  }else{
+    //Click on a widget over the panel
+    w->lh->_click(w->lh, m);
+  }
+}
+
+void
+_dclickPanel(Widget *w, Mouse *m){
+  if(!checkPanel(w)){
+    return;
+  }
+
+  w->_hover(w, m);
+
+  if (w->lh == nil){
+    //Click on the panel
+    if(w->dclick != nil){
+      w->dclick(w, m);
+      w->_redraw(w);
+    }
+  }else{
+    //Click on a widget over the panel
+    w->lh->_dclick(w->lh, m);
+  }
+}
+
+void
+_mPressDownPanel(Widget *w, Mouse *m){
+  if(!checkPanel(w)){
+    return;
+  }
+
+  w->_hover(w, m);
+
+  if (w->lh == nil){
+    //Press down mouse button on the panel
+    if(w->mpressdown != nil){
+      w->mpressdown(w, m);
+      w->_redraw(w);
+    }
+  }else{
+    //Press down mouse button on a widget over the panel
+    w->lh->_mpressdown(w->lh, m);
+  }
+}
+
+void
+_mPressUpPanel(Widget *w, Mouse *m){
+  if(!checkPanel(w)){
+    return;
+  }
+
+  w->_hover(w, m);
+
+  if (w->lh == nil){
+    //Press down mouse button on the panel
+    if(w->mpressup != nil){
+      w->mpressup(w, m);
+      w->_redraw(w);
+    }
+  }else{
+    //Press down mouse button on a widget over the panel
+    w->lh->_mpressup(w->lh, m);
+  }
+}

+ 17 - 0
sys/src/libjay/utils.c

@@ -0,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void _simpleResize(Widget *w, Point d){
+  w->p = Pt(w->p.x + d.x, w->p.y + d.y);
+  if (w->height > 0 && w->width > 0){
+    w->r = Rect(w->p.x, w->p.y, w->p.x + w->width, w->p.y + w->height);
+  }
+  if (w->resize != nil){
+    w->resize(w);
+  }
+}

+ 99 - 0
sys/src/libjay/widget.c

@@ -0,0 +1,99 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void setVisible(Widget *w, int visible);
+
+static Widget *
+genWidget(char *id, wtype t, void *w){
+  Widget *wr = malloc(sizeof(Widget));
+  if ( wr == nil){
+    return nil;
+  }
+  wr->id = strdup(id);
+  wr->p=ZP;
+  wr->r=ZR;
+  wr->t=t;
+  wr->w=w;
+  wr->i=nil;
+  wr->lh=nil;
+  wr->father=nil;
+  wr->hovered=0;
+  wr->visible=1;
+  wr->draw=nil;
+  wr->_draw=nil;
+  wr->_redraw=nil;
+  wr->hover=nil;
+  wr->_hover=nil;
+  wr->unhover=nil;
+  wr->_unhover=nil;
+  wr->resize=nil;
+  wr->click=nil;
+  wr->_click=nil;
+  wr->dclick=nil;
+  wr->_dclick=nil;
+  wr->mpressdown=nil;
+  wr->_mpressdown=nil;
+  wr->mpressup=nil;
+  wr->_mpressup=nil;
+  wr->change=nil;
+  wr->_change=nil;
+  wr->setVisible=setVisible;
+  return wr;
+}
+
+Widget *
+createWidget(char *id, int height, int width, wtype t, void *w){
+  Widget *wr = genWidget(id, t, w);
+  if ( wr == nil){
+    return nil;
+  }
+  wr->r=ZR;
+  wr->height = height;
+  wr->width = width;
+  if (height < 0 || width < 0){
+    wr->autosize=1;
+  } else {
+    wr->autosize = 0;
+  }
+  return wr;
+}
+
+Widget *
+createWidget1(char *id, Rectangle r, wtype t, void *w){
+  Widget *wr = genWidget(id, t, w);
+  if ( wr == nil){
+    return nil;
+  }
+  wr->r=r;
+  wr->height = r.max.y - r.min.y;
+  wr->width = r.max.x - r.min.x;
+  wr->autosize=0;
+  return wr;
+}
+
+static int
+checkWidget(Widget *w){
+  if (w == nil || w->w == nil || w->father == nil){
+    return 0;
+  }
+  return 1;
+}
+
+void
+setVisible(Widget *w, int visible){
+  if(!checkWidget(w)){
+    return;
+  }
+  w->visible=visible;
+  if (visible){
+    w->_redraw(w);
+  } else {
+    //To dissapear we need to redraw the father
+    w->father->_redraw(w->father);
+  }
+}

+ 100 - 0
sys/src/libjay/window.c

@@ -0,0 +1,100 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+void mousethread(void* v);
+
+const unsigned long jaystacksize = 8192;
+
+Mousectl *m;
+
+Widget *
+initjayapp(char *name){
+  if(initdraw(nil, nil, name) < 0){
+    sysfatal("initdraw failed");
+  }
+
+  m = initmouse(nil, screen);
+  if (m == nil){
+    sysfatal("mouse error");
+  }
+  initdefaultconfig();
+  Widget *w = createPanel1("main", screen->r, screen->r.min);
+  if (w == nil){
+    sysfatal("createPanel failed");
+  }
+  return w;
+}
+
+void
+startjayapp(Widget * w){
+  Channel *exitchan;
+  if (w == nil){
+    sysfatal("startjayapp nil widget");
+  }
+  exitchan = chancreate(sizeof(int), 0);
+  w->_draw(w, screen);
+  flushimage(display, 1);
+  yield();
+  threadcreate(mousethread, w, jaystacksize);
+  recv(exitchan, nil);
+}
+
+void
+mousethread(void* v){
+  Widget *w = v;
+  unsigned int msec = 0;
+  int button = 0;
+  int isdown = 0;
+  threadsetname("mousethread");
+  enum {
+		MReshape,
+		MMouse,
+		NALT
+	};
+	static Alt alts[NALT+1];
+  alts[MReshape].c = m->resizec;
+	alts[MReshape].v = nil;
+	alts[MReshape].op = CHANRCV;
+	alts[MMouse].c = m->c;
+	alts[MMouse].v = (Mouse *)m;
+	alts[MMouse].op = CHANRCV;
+	alts[NALT].op = CHANEND;
+  for(;;){
+    switch(alt(alts)){
+      case MMouse:
+        if(m->buttons != 0){
+          if(msec == 0 || button != m->buttons || (m->msec - msec) > jayconfig->doubleclickTime){
+            msec = m->msec;
+            button = m->buttons;
+            isdown = 1;
+            w->_mpressdown(w, (Mouse*)m);
+          } else if(!isdown){
+            w->_dclick(w, (Mouse *)m);
+            msec = 0;
+            button = 0;
+            isdown = 0;
+          }
+        } else if (isdown){
+          msec = m->msec;
+          w->_mpressup(w, (Mouse *)m);
+          w->_click(w, (Mouse *)m);
+          isdown=0;
+        } else {
+          w->_hover(w, (Mouse *)m);
+        }
+        break;
+      case MReshape:
+        if (getwindow(display, Refnone)<0){
+          sysfatal("failed to re-attach window");
+        }
+        Point d = Pt(screen->r.min.x - w->p.x, screen->r.min.y - w->p.y);
+        w->_resize(w, d);
+        break;
+    }
+  }
+}

+ 51 - 0
sys/src/libjay/wlist.c

@@ -0,0 +1,51 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+#include "fns.h"
+
+WListElement *
+createWListElement(Widget *w){
+  WListElement *e = malloc(sizeof(WListElement));
+  if (e == nil){
+    return nil;
+  }
+  e->next=nil;
+  e->prev=nil;
+  e->w=w;
+  return e;
+}
+
+WListElement *
+getWListElementByID(WListElement *list, char *id){
+  for(WListElement *e = list; e != nil ; e=e->next ){
+    if(strcmp(id, e->w->id) == 0){
+      return e;
+    }
+  }
+  return nil;
+}
+
+int
+addWListElement(WListElement *list, Widget *w){
+  if(list == nil){
+    return 0;
+  }
+  if(getWListElementByID(list, w->id) != nil){
+    return 0;
+  }
+  WListElement *le = createWListElement(w);
+  if(le == nil){
+    return 0;
+  }
+  for(WListElement *e = list; e != nil ; e=e->next ){
+    if(e->next == nil){
+      e->next = le;
+      le->prev = e;
+      return 1;
+    }
+  }
+  return 0;
+}

+ 1 - 0
sys/src/libs.json

@@ -19,6 +19,7 @@
 			"/sys/src/libfreetype/libfreetype.json",
 			"/sys/src/libgeometry/libgeometry.json",
 			"/sys/src/libhttpd/libhttpd.json",
+			"/sys/src/libjay/libjay.json",
 			"/sys/src/liblex/liblex.json",
 			"/sys/src/libmach/libmach.json",
 			"/sys/src/libmemdraw/libmemdraw.json",

+ 13 - 0
sys/src/test/build.json

@@ -0,0 +1,13 @@
+{
+  "Tests": {
+		"CFlags": [],
+		"Include": [
+			"../cmd/cmd.json"
+		],
+    "Install": "/usr/harvey/",
+    "Program": "labels",
+    "SourceFiles": [
+			"labels.c"
+		]
+}
+}

+ 156 - 0
sys/src/test/labels.c

@@ -0,0 +1,156 @@
+/*
+ * labels: little program to test libjay
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <jay.h>
+
+void onHover_L1(Widget *w);
+void onClick_L1(Widget *w, Mouse *m);
+
+void onHover_L2(Widget *w);
+void onClick_L2(Widget *w, Mouse *m);
+void onDClick_L2(Widget *w, Mouse *m);
+
+void onClick_L3(Widget *w, Mouse *m);
+
+void onClick_L4(Widget *w, Mouse *m);
+void onChange_L4(Widget *w);
+
+void onPress(Widget *w, Mouse *m);
+void onRelease(Widget *w, Mouse *m);
+
+void
+threadmain(int argc, char *argv[]) {
+  Widget * w = initjayapp("labels");
+  if (w==nil){
+    sysfatal("Error initial panel");
+  }
+
+  Widget *l = createLabel("label1", -1, -1);
+  Widget *l2 = createLabel("label2", 20, 120);
+  Widget *l3 = createLabel("label3", 20, 200);
+  Widget *l4 = createLabel("label4", 20, 270);
+
+  Label *aux = l->w;
+  aux->setText(aux, "This is a label with autosize");
+  aux->border=1;
+  l->hover=onHover_L1;
+  l->unhover=onHover_L1;
+  l->click=onClick_L1;
+  w->addWidget(w, l, Pt(30,30));
+
+  aux = l2->w;
+  aux->setText(aux, "Click me");
+  aux->border=1;
+  aux->d3=1;
+  l2->click=onClick_L2;
+  l2->dclick=onDClick_L2;
+  l2->hover = onHover_L2;
+  l2->unhover = onHover_L2;
+  w->addWidget(w, l2, Pt(30,60));
+
+  aux = l3->w;
+  aux->setText(aux, "Click on me to dissapear");
+  l3->click=onClick_L3;
+  w->addWidget(w, l3, Pt(30, 90));
+
+  aux = l4->w;
+  aux->setText(aux, "Click to change text and color");
+  l4->change=onChange_L4;
+  l4->click=onClick_L4;
+  w->addWidget(w, l4, Pt(30, 120));
+
+  startjayapp(w);
+  threadexits(nil);
+}
+
+
+void onHover_L1(Widget *w){
+  Label *l = w->w;
+  if(w->hovered){
+    l->border=3;
+  } else {
+    l->border=1;
+  }
+}
+
+void onHover_L2(Widget *w){
+  Label *l = w->w;
+  if(w->hovered){
+    l->up=1;
+  } else {
+    l->up=0;
+  }
+}
+
+void onClick_L1(Widget *w, Mouse *m){
+  static int i = 1;
+  Label *l = w->w;
+  if (i){
+    l->setText(l, "A large text in the label");
+    i=0;
+  } else {
+    l->setText(l, "Short text");
+    i=1;
+  }
+}
+
+void onClick_L2(Widget *w, Mouse *m){
+  static int i = 1;
+  Label *l = w->w;
+  if (i){
+    l->setText(l, "One click");
+    i=0;
+  } else {
+    l->setText(l, "Just one click");
+    i=1;
+  }
+}
+
+void onClick_L4(Widget *w, Mouse *m){
+  static int i = 1;
+  Label *l = w->w;
+  if (i){
+    l->setText(l, "Click me to change text and color");
+    i=0;
+  } else {
+    l->setText(l, "Click to change text and color!");
+    i=1;
+  }
+}
+
+void onChange_L4(Widget *w){
+  static int i=1;
+  Label *l = w->w;
+  if (i) {
+    l->textColor=DRed;
+    i=0;
+  } else {
+    l->textColor=DBlack;
+    i=1;
+  }
+}
+
+void onClick_L3(Widget *w, Mouse *m){
+  w->setVisible(w, 0);
+}
+
+void onDClick_L2(Widget *w, Mouse *m){
+  Label *l = w->w;
+  l->setText(l, "Double click");
+}
+
+void onPress(Widget *w, Mouse *m){
+  Label *l = w->w;
+  l->border=0;
+}
+
+void onRelease(Widget *w, Mouse *m){
+  Label *l = w->w;
+  l->border=1;
+}