fix dnd added empty file path to the playlist
[uwplayer.git] / application / Sidebar.c
index a3dd20a..733e21a 100644 (file)
@@ -29,6 +29,9 @@
 #include <errno.h>
 
 #include "xdnd.h"
+#include "utils.h"
+#include "playlist.h"
+#include <cx/string.h>
 
 
 static void sidebar_class_init(void);
@@ -41,9 +44,10 @@ static void sidebar_expose(Widget widget, XEvent *event, Region      region);
 static Boolean sidebar_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args);
 static void sidebar_insert_child(Widget child);
 Boolean sidebar_acceptfocus(Widget widget, Time *time);
-static void FocusInAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
 
-static void xdndEnterAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
+static void FocusInAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
+static void SelectElmAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
+static void PopupAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
 
 static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata);
 
@@ -54,12 +58,13 @@ static XtResource resources[] = {
 
 static XtActionsRec actionslist[] = {
   {"focusIn", FocusInAP},
-  {"xdnd_enter", xdndEnterAP},
-  {"NULL", NULL}
+  {"selectElm", SelectElmAP},
+  {"popup", PopupAP}
 };
 
-static char defaultTranslations[] = "<FocusIn>:                        focusIn()\n"
-                                    "<Message>XdndEnter:    xdnd_enter()\n";
+static char defaultTranslations[] = "<FocusIn>:  focusIn()\n"
+                                    "<Btn1Down>: selectElm()\n"
+                                    "<Btn3Down>: popup()";
 
 
 static XtResource constraints[] = {};
@@ -152,7 +157,42 @@ static void sidebar_class_part_init (WidgetClass wc) {
 
 
 static void sidebar_init(Widget request, Widget neww, ArgList args, Cardinal *num_args) {
+    Sidebar sb = (Sidebar)neww;
+    
+    // initialize everything except XftDraw or other stuff that needs a Window
+    
+    XftColor fg, bg, sel2;
+    fg.color.red = 0;
+    fg.color.green = 0;
+    fg.color.blue = 0;
+    fg.color.alpha = 0xFFFF;
+    
+    bg.color.red = 0xFFFF;
+    bg.color.green = 0xFFFF;
+    bg.color.blue = 0xFFFF;
+    bg.color.alpha = 0xFFFF;
+    
+    sel2.color.red = 0xFFFF;
+    sel2.color.green = 0xFFFF;
+    sel2.color.blue = 0;
+    sel2.color.alpha = 0xFFFF;
+    
+    sb->sidebar.fg = fg;
+    sb->sidebar.bg = bg;
+    sb->sidebar.select2_bg = sel2;
+    
+    sb->sidebar.select2 = -1;
+    
+    sb->sidebar.font = FontFromName(XtDisplay(neww), "Sans:size=11");
+    if(!sb->sidebar.font) {
+        fprintf(stderr, "Cannot open font.\nAbort.\n");
+        exit(-1);
+    }
     
+    XftFont *xftFont = sb->sidebar.font->fonts->font;
+    int padding = 2;
+    int fontheight = xftFont->ascent;
+    sb->sidebar.elmHeight = fontheight + 2*padding;
 }
 
 
@@ -161,10 +201,27 @@ static void sidebar_destroy(Widget widget) {
     
 }
 
+static int testresize = 1;
 static void sidebar_resize(Widget widget) {
-    
+    if(testresize) {
+        XtWidgetGeometry geom;
+        geom.request_mode = CWWidth | CWHeight;
+        geom.width = 200;
+        geom.height = 2000;
+        XtWidgetGeometry result;
+        //XtMakeGeometryRequest(widget, &geom, &result);
+        testresize = 0;
+    }
+    printf("resize\n");
 }
 
+
+static void remove_cb(Widget item, XtPointer index, XtPointer cd) {
+    printf("test_cb\n");
+    fflush(stdout);
+}
+
+
 static int xdnd_initialized = 0;
 
 static void sidebar_realize(Widget widget, XtValueMask *mask, XSetWindowAttributes *attributes) {
@@ -174,12 +231,84 @@ static void sidebar_realize(Widget widget, XtValueMask *mask, XSetWindowAttribut
         XdndInit(XtDisplay(widget), XtWidgetToApplicationContext(widget), sidebar_xdnd_callback, widget);
     }
     XdndEnable(widget);
+    
+    Screen *screen = widget->core.screen;
+    Visual *visual = screen->root_visual;
+    for(int i=0;i<screen->ndepths;i++) {
+        Depth d = screen->depths[i];
+        if(d.depth == widget->core.depth) {
+            visual = d.visuals;
+            break;
+        }
+    }
+    
+    Sidebar sb = (Sidebar)widget;
+    sb->sidebar.d = XftDrawCreate(
+            XtDisplay(widget),
+            XtWindow(widget),
+            visual,
+            widget->core.colormap);
+    
+    Dimension w, h;
+    
+    Widget parent = XtParent(widget);
+    XtVaSetValues(parent, XmNbackground, WhitePixelOfScreen(XtScreen(parent)), NULL);
+    
+    XtMakeResizeRequest(widget, 200, 100, &w, &h);
+    
+    
+    XmString s1 = XmStringCreateSimple("Remove");
+    sb->sidebar.popupMenu = XmVaCreateSimplePopupMenu(
+            widget, "popup", remove_cb,
+            //XmNuserData, widget,
+            XmVaPUSHBUTTON, s1, 'R', NULL, NULL,
+            NULL);
+    XmStringFree(s1);
 }
 
 static void sidebar_expose(Widget widget, XEvent *event, Region        region) {
-    printf("expose\n");
+    //printf("expose\n");
     Dimension w, h;
-    XtMakeResizeRequest(widget, 200, 200, &w, &h);
+    //XtMakeResizeRequest(widget, 200, 2000, &w, &h);
+    
+    w = widget->core.width;
+    h = widget->core.height;
+    
+    Widget parent = XtParent(widget);
+    
+    Sidebar s = (Sidebar)widget;
+    XftFont *xftFont = s->sidebar.font->fonts->font;
+    CxList *tracks = s->sidebar.window->playlist.tracks;
+    size_t numTracks = tracks->size;
+    
+    int fontheight = xftFont->ascent;
+    int height = s->sidebar.elmHeight;
+    
+    
+    int list_height = numTracks * height;
+    if((list_height > s->core.height) || (w < parent->core.width)) {
+        XtMakeResizeRequest(widget, parent->core.width, list_height + 5, &w, &h);
+    }
+    
+    
+    XftDrawRect(s->sidebar.d, &s->sidebar.bg, 0, 0, w, h);
+    
+    
+    //printf("current track: %d\n", s->sidebar.window->playlist.current_track);
+    
+    CxIterator i = cxListIterator(s->sidebar.window->playlist.tracks);
+    cx_foreach(const char *, elm, i) {
+        const char *name = util_resource_name(elm);
+        XftColor *cg = &s->sidebar.fg;
+        if(i.index == s->sidebar.window->playlist.current_track) {
+            XftDrawRect(s->sidebar.d, &s->sidebar.fg, 0, i.index*height, s->core.width, height);
+            cg = &s->sidebar.bg;
+        } else if(i.index == s->sidebar.select2) {
+            XftDrawRect(s->sidebar.d, &s->sidebar.select2_bg, 0, i.index*height, s->core.width, height);
+        }
+        
+        XftDrawString8(s->sidebar.d, cg, s->sidebar.font->fonts->font, 10, i.index*height + xftFont->ascent, (const FcChar8*)name, strlen(name));
+    }
 }
 
 static Boolean sidebar_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) {
@@ -198,25 +327,44 @@ Boolean sidebar_acceptfocus(Widget widget, Time *time) {
 
 
 static void FocusInAP(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
-    printf("focusin\n");
-    fflush(stdout);
+    
 }
 
-static void xdndEnterAP(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
-    printf("xdndEnterAP\n");
-    fflush(stdout);
+static void SelectElmAP(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
+    //printf("btn1\n");
+    XButtonEvent *e = &event->xbutton;
+    Sidebar s = (Sidebar)w;
+    
+    int selected = e->y / s->sidebar.elmHeight;
+    PlayListPlayTrack(s->sidebar.window, selected);
+    s->sidebar.select2 = -1;
+    
+    SidebarRepaint(w);
 }
 
+static void PopupAP(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
+    XButtonEvent *e = &event->xbutton;
+    Sidebar s = (Sidebar)w;
+    
+    int selected = e->y / s->sidebar.elmHeight;
+    s->sidebar.select2 = selected;
+    SidebarRepaint(w);
+    
+    //printf("btn3\n");
+    //fflush(stdout);
+    
+    XmMenuPosition(s->sidebar.popupMenu, &event->xbutton);
+    XtManageChild(s->sidebar.popupMenu);
+}
 
 
-
-static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata) {
-    printf("xdnd\n");
-    fflush(stdout);
-    
-    char *urilist = udata;
+static void open_uri(Sidebar s, cxstring uri) {
+    if(uri.length == 0) {
+        return;
+    }
     
-    size_t len = strlen(urilist);
+    const char *urilist = uri.ptr;
+    size_t len = uri.length;
     
     size_t start = 0;
     if(len > 7 && !memcmp(urilist, "file://", 7)) {
@@ -261,12 +409,28 @@ static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata) {
     }
     path[k] = '\0';
     
-    // add file
-    // TODO
+    PlayListAddFile(s->sidebar.window, path);
     
     free(path);
 }
 
+static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata) {
+    printf("xdnd\n");
+    fflush(stdout);
+    
+    Sidebar s = (Sidebar)cdata;
+    
+    cxstring urllist = cx_str(udata);
+    
+    CxStrtokCtx tk = cx_strtok(urllist, cx_str("\r\n"), INT_MAX);
+    cxstring uri;
+    while(cx_strtok_next(&tk, &uri)) {
+        open_uri(s, uri);
+    }
+    
+    SidebarRepaint((Widget)s);
+}
+
 
 /* --------------------------- public --------------------------- */
 
@@ -278,3 +442,12 @@ Widget CreateSidebar(
 {
     return XtCreateWidget(name, xnSidebarWidgetClass, parent, arglist, argcount);
 }
+
+void SidebarSetWindow(Widget widget, MainWindow *win) {
+    Sidebar sb = (Sidebar)widget;
+    sb->sidebar.window = win;
+}
+
+void SidebarRepaint(Widget widget) {
+    XClearArea(XtDisplay(widget), XtWindow(widget), 0, 0, widget->core.width, widget->core.height, true);
+}