From a0b7282b31ed31051ee98bf16e8704d5599e5461 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 6 Mar 2013 09:30:52 +0100 Subject: Major GUI workover. Hilights: A new filebrowser and new knob widget. --- plugingui/Makefile.am.plugingui | 5 +- plugingui/Makefile.mingw32 | 3 + plugingui/eventhandler.cc | 63 +++++++++---- plugingui/eventhandler.h | 2 +- plugingui/filebrowser.cc | 151 +++++++++++++++++++++++++++++++ plugingui/filebrowser.h | 62 +++++++++++++ plugingui/font.h | 2 +- plugingui/guievent.h | 13 +-- plugingui/knob.cc | 167 ++++++++++++++++++++++++++++++++++ plugingui/knob.h | 73 +++++++++++++++ plugingui/lineedit.cc | 1 + plugingui/listbox.cc | 170 +++++++++++++++++++++++++++++++++++ plugingui/listbox.h | 71 +++++++++++++++ plugingui/nativewindow.h | 1 + plugingui/nativewindow_win32.cc | 8 +- plugingui/nativewindow_win32.h | 1 + plugingui/nativewindow_x11.cc | 6 ++ plugingui/nativewindow_x11.h | 1 + plugingui/painter.cc | 179 ++++++++++++++++++++++++++++++++++++- plugingui/painter.h | 8 +- plugingui/pixelbuffer.cc | 29 +++++- plugingui/pixelbuffer.h | 6 ++ plugingui/plugingui.cc | 193 ++++++++++++++++++++++++++++------------ plugingui/plugingui.h | 10 ++- plugingui/slider.cc | 14 ++- plugingui/widget.cc | 82 ++++++++++++++--- plugingui/widget.h | 15 +++- plugingui/window.cc | 3 + plugingui/window.h | 2 + 29 files changed, 1231 insertions(+), 110 deletions(-) create mode 100644 plugingui/filebrowser.cc create mode 100644 plugingui/filebrowser.h create mode 100644 plugingui/knob.cc create mode 100644 plugingui/knob.h create mode 100644 plugingui/listbox.cc create mode 100644 plugingui/listbox.h (limited to 'plugingui') diff --git a/plugingui/Makefile.am.plugingui b/plugingui/Makefile.am.plugingui index 4755ebd..6ce79fc 100644 --- a/plugingui/Makefile.am.plugingui +++ b/plugingui/Makefile.am.plugingui @@ -18,7 +18,10 @@ PLUGIN_GUI_SOURCES = \ $(top_srcdir)/plugingui/lineedit.cc \ $(top_srcdir)/plugingui/led.cc \ $(top_srcdir)/plugingui/checkbox.cc \ - $(top_srcdir)/plugingui/slider.cc + $(top_srcdir)/plugingui/slider.cc \ + $(top_srcdir)/plugingui/listbox.cc \ + $(top_srcdir)/plugingui/knob.cc \ + $(top_srcdir)/plugingui/filebrowser.cc PLUGIN_GUI_LIBS = -lX11 diff --git a/plugingui/Makefile.mingw32 b/plugingui/Makefile.mingw32 index 83f4f04..08e772e 100644 --- a/plugingui/Makefile.mingw32 +++ b/plugingui/Makefile.mingw32 @@ -29,6 +29,9 @@ CXX_SOURCES = \ $(top_srcdir)/plugingui/led.cc \ $(top_srcdir)/plugingui/checkbox.cc \ $(top_srcdir)/plugingui/slider.cc \ + $(top_srcdir)/plugingui/listbox.cc \ + $(top_srcdir)/plugingui/filebrowser.cc \ + $(top_srcdir)/plugingui/knob.cc \ $(top_srcdir)/src/thread.cc OBJECTS=$(CXX_SOURCES:.cc=.o) $(C_SOURCES:.c=.o) diff --git a/plugingui/eventhandler.cc b/plugingui/eventhandler.cc index fdef990..3570b77 100644 --- a/plugingui/eventhandler.cc +++ b/plugingui/eventhandler.cc @@ -37,6 +37,7 @@ GUI::EventHandler::EventHandler(GlobalContext *gctx) { this->gctx = gctx; + last_click = 0; #ifdef WIN32 this->gctx->eventhandler = this; event = NULL; @@ -66,7 +67,6 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) GUI::EventHandler *handler = (GUI::EventHandler *) GetWindowLong(hwnd, GWL_USERDATA); - switch(msg) { case WM_SIZE: { @@ -142,6 +142,8 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) // fwKeys = wp; break; + case WM_LBUTTONDBLCLK: + printf("LBUTTONDBLCLK\n"); case WM_LBUTTONDOWN: { GUI::ButtonEvent *e = new GUI::ButtonEvent(); @@ -149,6 +151,7 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) e->y = (int)(short) HIWORD(lp); e->button = 0; e->direction = 1; + e->doubleclick = (msg == WM_LBUTTONDBLCLK); handler->event = e; } //xPos = (int)(short) LOWORD(lp); @@ -157,18 +160,29 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) break; case WM_MBUTTONUP: + { + GUI::ButtonEvent *e = new GUI::ButtonEvent(); + e->x = (int)(short) LOWORD(lp); + e->y = (int)(short) HIWORD(lp); + e->button = 3; + e->direction = -1; + e->doubleclick = 0; + handler->event = e; + } //xPos = (int)(short) LOWORD(lp); //yPos = (int)(short) HIWORD(lp); //fwKeys = wp; break; + case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: { GUI::ButtonEvent *e = new GUI::ButtonEvent(); e->x = (int)(short) LOWORD(lp); e->y = (int)(short) HIWORD(lp); - e->button = 1; + e->button = 3; e->direction = 1; + e->doubleclick = (msg == WM_MBUTTONDBLCLK); handler->event = e; } // xPos = (int)(short) LOWORD(lp); @@ -183,6 +197,7 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) e->y = (int)(short) HIWORD(lp); e->button = 1; e->direction = -1; + e->doubleclick = 0; handler->event = e; } // xPos = (int)(short) LOWORD(lp); @@ -190,6 +205,7 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) // fwKeys = wp; break; + case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: { GUI::ButtonEvent *e = new GUI::ButtonEvent(); @@ -197,6 +213,7 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) e->y = (int)(short) HIWORD(lp); e->button = 1; e->direction = 1; + e->doubleclick = (msg == WM_RBUTTONDBLCLK); handler->event = e; } // xPos = (int)(short) LOWORD(lp); @@ -469,6 +486,10 @@ GUI::Event *GUI::EventHandler::getNextEvent() e->y = xe.xbutton.y; e->button = 0; e->direction = xe.type == ButtonPress?1:-1; + e->doubleclick = + xe.type == ButtonPress && (xe.xbutton.time - last_click) < 200; + + if(xe.type == ButtonPress) last_click = xe.xbutton.time; event = e; } @@ -542,14 +563,16 @@ void GUI::EventHandler::processEvents(Window *window) // window->repaint((RepaintEvent*)event); window->redraw(); break; - case Event::Resize:{ - // window->repaint((RepaintEvent*)event) - ResizeEvent *re = (ResizeEvent*)event; - if(re->width != window->width() || re->height != window->height()) { - window->resized(re->width, re->height); - window->repaint_r(NULL); + case Event::Resize: + { + // window->repaint((RepaintEvent*)event) + ResizeEvent *re = (ResizeEvent*)event; + if(re->width != window->width() || re->height != window->height()) { + window->resized(re->width, re->height); + window->repaint_r(NULL); + } } - } break; + break; case Event::MouseMove: { MouseMoveEvent *me = (MouseMoveEvent*)event; @@ -558,21 +581,22 @@ void GUI::EventHandler::processEvents(Window *window) if(window->buttonDownFocus()) { Widget *w = window->buttonDownFocus(); + /* if(me->x < w->x()) me->x = w->x(); if(me->x > w->x() + w->width()) me->x = w->x() + w->width(); if(me->y < w->y()) me->y = w->y(); if(me->y > w->y() + w->height()) me->y = w->y() + w->height(); - - me->x -= w->x(); - me->y -= w->y(); + */ + me->x -= w->windowX(); + me->y -= w->windowY(); window->buttonDownFocus()->mouseMoveEvent(me); break; } if(w) { - me->x -= w->x(); - me->y -= w->y(); + me->x -= w->windowX(); + me->y -= w->windowY(); w->mouseMoveEvent(me); } } @@ -586,13 +610,14 @@ void GUI::EventHandler::processEvents(Window *window) if(window->buttonDownFocus()) { if(be->direction == -1) { Widget *w = window->buttonDownFocus(); + /* if(be->x < w->x()) be->x = w->x(); if(be->x > w->x() + w->width()) be->x = w->x() + w->width(); if(be->y < w->y()) be->y = w->y(); if(be->y > w->y() + w->height()) be->y = w->y() + w->height(); - - be->x -= w->x(); - be->y -= w->y(); + */ + be->x -= w->windowX(); + be->y -= w->windowY(); w->buttonEvent(be); break; @@ -602,8 +627,8 @@ void GUI::EventHandler::processEvents(Window *window) } if(w) { - be->x -= w->x(); - be->y -= w->y(); + be->x -= w->windowX(); + be->y -= w->windowY(); w->buttonEvent(be); diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h index c63c003..99be2d4 100644 --- a/plugingui/eventhandler.h +++ b/plugingui/eventhandler.h @@ -52,7 +52,7 @@ public: GlobalContext *gctx; private: - + int last_click; void (*closeHandler)(void *); void *closeHandlerPtr; }; diff --git a/plugingui/filebrowser.cc b/plugingui/filebrowser.cc new file mode 100644 index 0000000..6582202 --- /dev/null +++ b/plugingui/filebrowser.cc @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filebrowser.cc + * + * Mon Feb 25 21:09:44 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "filebrowser.h" + +#include "painter.h" + +#include "button.h" +#include "listbox.h" + +#include +#include +#include + +#include +#include +#include + +struct GUI::FileBrowser::private_data { + GUI::ListBox *listbox; + void (*filesel_handler)(void *, std::string); + void *ptr; +}; + +void changeDir(void *ptr) +{ + struct GUI::FileBrowser::private_data *prv = + (struct GUI::FileBrowser::private_data *)ptr; + + GUI::ListBox *lb = prv->listbox; + std::string value = lb->selectedValue(); + + char filename[1024]; + char *c = getcwd(filename, sizeof(filename)); + (void)c; + strcat(filename, "/"); + strcat(filename, value.c_str()); + + struct stat st; + if(stat(filename, &st) == 0) { + if((st.st_mode & S_IFDIR) != 0) { + //printf("'%s' is present and is a directory\n", filename); + } + if((st.st_mode & S_IFREG) != 0) { + //printf("'%s' is present and is a file\n", filename); + if(prv->filesel_handler) prv->filesel_handler(prv->ptr, filename); + return; + } + } else { + //printf("'%s' is not present or unreadable\n", filename); + return; + } + + lb->clear(); + int i = chdir(value.c_str()); + (void)i; + DIR *dir = opendir("."); + + struct dirent *entry; + while((entry = readdir(dir)) != NULL) { + lb->addItem(entry->d_name, entry->d_name); + } + + closedir(dir); +} + +GUI::FileBrowser::FileBrowser(GUI::Widget *parent) + : GUI::Widget(parent) +{ + prv = new struct GUI::FileBrowser::private_data(); + prv->filesel_handler = NULL; + +#define brd 5 // border +#define btn_h 12 + + listbox = new GUI::ListBox(this); + listbox->registerDblClickHandler(changeDir, prv); + prv->listbox = listbox; + + btn = new GUI::Button(this); + btn->setText("Select"); + btn->registerClickHandler(changeDir, prv); + + changeDir(prv); + + resize(200, 190); +} + +GUI::FileBrowser::~FileBrowser() +{ + delete prv->listbox; + delete prv; +} + +void GUI::FileBrowser::resize(size_t w, size_t h) +{ + GUI::Widget::resize(w,h); + + listbox->move(brd, brd); + listbox->resize(w - 1 - 2*brd, h - btn_h - 3*brd); + + btn->move(brd, h - btn_h - brd); + btn->resize(w - 1 - 2*brd, btn_h); +} + + +void GUI::FileBrowser::registerFileSelectHandler(void (*handler)(void *, + std::string), + void *ptr) +{ + prv->filesel_handler = handler; + prv->ptr = ptr; +} + +void GUI::FileBrowser::repaintEvent(GUI::RepaintEvent *e) +{ + Painter p(this); + p.setColour(Colour(0, 0.8)); + + p.drawFilledRectangle(0, 0, width(), height()); + + p.setColour(Colour(1, 1)); + + for(int i = 1; i < 10; i++) { + p.drawLine(0,0,width() / i, height() - 1); + p.drawLine(width()-1,0,width() / i, height() - 1); + } +} diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h new file mode 100644 index 0000000..bdfe98f --- /dev/null +++ b/plugingui/filebrowser.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filebrowser.h + * + * Mon Feb 25 21:09:43 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_FILEBROWSER_H__ +#define __DRUMGIZMO_FILEBROWSER_H__ + +#include "widget.h" + +#include "button.h" +#include "listbox.h" + +namespace GUI { + +class FileBrowser : public Widget { +public: + struct private_data; + + FileBrowser(Widget *parent); + ~FileBrowser(); + + bool isFocusable() { return true; } + + void registerFileSelectHandler(void (*handler)(void *, std::string), + void *ptr); + + virtual void repaintEvent(RepaintEvent *e); + + virtual void resize(size_t w, size_t h); + +private: + struct private_data *prv; + + GUI::ListBox *listbox; + GUI::Button *btn; +}; + +}; + +#endif/*__DRUMGIZMO_FILEBROWSER_H__*/ diff --git a/plugingui/font.h b/plugingui/font.h index c83a98f..848b168 100644 --- a/plugingui/font.h +++ b/plugingui/font.h @@ -46,7 +46,7 @@ public: size_t size(); size_t textWidth(std::string text); - size_t textHeight(std::string text); + size_t textHeight(std::string text = ""); PixelBufferAlpha *render(GlobalContext *gctx, std::string text); diff --git a/plugingui/guievent.h b/plugingui/guievent.h index 0fb3ef2..d8d6955 100644 --- a/plugingui/guievent.h +++ b/plugingui/guievent.h @@ -61,27 +61,28 @@ class MouseMoveEvent : public Event { public: Type type() { return MouseMove; } - size_t x; - size_t y; + int x; + int y; }; class ButtonEvent : public Event { public: Type type() { return Button; } - size_t x; - size_t y; + int x; + int y; int direction; int button; + int doubleclick; }; class RepaintEvent : public Event { public: Type type() { return Repaint; } - size_t x; - size_t y; + int x; + int y; size_t width; size_t height; }; diff --git a/plugingui/knob.cc b/plugingui/knob.cc new file mode 100644 index 0000000..75a7278 --- /dev/null +++ b/plugingui/knob.cc @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * knob.cc + * + * Thu Feb 28 07:37:27 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "knob.h" + +#include "painter.h" + +#include +#include +#include + +GUI::Knob::Knob(Widget *parent) + : GUI::Widget(parent) +{ + state = up; + + val = 0.0; + maximum = 1.0; + minimum = 0.0; + mouse_offset_x = 0; + + handler = NULL; + ptr = NULL; +} + +void GUI::Knob::setValue(float v) +{ + val = v; + if(handler) handler(ptr); + repaintEvent(NULL); +} + +float GUI::Knob::value() +{ + return val; +} + +void GUI::Knob::registerClickHandler(void (*handler)(void *), void *ptr) +{ + this->handler = handler; + this->ptr = ptr; +} + +void GUI::Knob::mouseMoveEvent(MouseMoveEvent *e) +{ + if(state == down) { + /* + DEBUG(slider, "Knob::mouseMoveEvent(mouse_offset_x: %d, e->x: %d)\n", + mouse_offset_x, e->x); + */ + if(mouse_offset_x == (e->x + -1*e->y)) return; + + float dval = mouse_offset_x - (e->x + -1*e->y); + val -= dval / 300.0; + + if(val < 0) val = 0; + if(val > 1) val = 1; + + if(handler) handler(ptr); + repaintEvent(NULL); + + mouse_offset_x = e->x + -1*e->y; + } +} + +void GUI::Knob::buttonEvent(ButtonEvent *e) +{ + if(e->direction == 1) { + state = down; + mouse_offset_x = e->x + -1*e->y; + //val = maximum / (float)width() * (float)e->x; + if(handler) handler(ptr); + repaintEvent(NULL); + } + if(e->direction == -1) { + state = up; + mouse_offset_x = e->x + -1*e->y; + //val = maximum / (float)width() * (float)e->x; + repaintEvent(NULL); + clicked(); + if(handler) handler(ptr); + } +} + +void GUI::Knob::repaintEvent(GUI::RepaintEvent *e) +{ + // DEBUG(slider, "Knob::repaintEvent (%f)\n", val); + + Painter p(this); + + float alpha = 0.8; + + p.setColour(Colour(0, 0)); + p.drawFilledRectangle(0,0,width()-1,height()-1); + + if(hasKeyboardFocus()) { + p.setColour(Colour(0.6, alpha)); + } else { + p.setColour(Colour(0.5, alpha)); + } + + int radius = (width()>height()?height():width()) / 2; + int center_x = width() / 2; + int center_y = height() / 2; + + p.setColour(Colour(1, alpha)); + + char buf[64]; + sprintf(buf, "%.2f", val * maximum); + Font font; + p.drawText(center_x - font.textWidth(buf) / 2, + center_y + font.textHeight(buf) / 2, font, buf); + + p.setColour(Colour(0.5, 0.5, 1, alpha)); + + p.drawCircle(center_x, center_y, radius); + + double padval = val * 0.8 + 0.1; + double border_x = sin((-1 * padval + 1) * 2 * M_PI); + double border_y = cos((-1 * padval + 1) * 2 * M_PI); + + p.setColour(Colour(1, 0, 0, alpha)); + p.drawLine(border_x * (radius / 2) + center_x, + border_y * (radius / 2) + center_y, + border_x * radius + center_x, + border_y * radius + center_y); +} + +#ifdef TEST_KNOB +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_KNOB*/ diff --git a/plugingui/knob.h b/plugingui/knob.h new file mode 100644 index 0000000..98ccf36 --- /dev/null +++ b/plugingui/knob.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * knob.h + * + * Thu Feb 28 07:37:27 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_KNOB_H__ +#define __DRUMGIZMO_KNOB_H__ + +#include "widget.h" + +namespace GUI { + +class Knob : public Widget { +public: + Knob(Widget *parent); + + bool catchMouse() { return true; } + + void setValue(float value); + float value(); + + void registerClickHandler(void (*handler)(void *), void *ptr); + + //protected: + virtual void clicked() {} + + virtual void repaintEvent(RepaintEvent *e); + virtual void buttonEvent(ButtonEvent *e); + virtual void mouseMoveEvent(MouseMoveEvent *e); + +private: + typedef enum { + up, + down + } state_t; + + float val; + float maximum; + float minimum; + + state_t state; + + void (*handler)(void *); + void *ptr; + + int mouse_offset_x; + +}; + +}; + +#endif/*__DRUMGIZMO_KNOB_H__*/ diff --git a/plugingui/lineedit.cc b/plugingui/lineedit.cc index 033acd1..c799e32 100644 --- a/plugingui/lineedit.cc +++ b/plugingui/lineedit.cc @@ -43,6 +43,7 @@ GUI::LineEdit::LineEdit(Widget *parent) void GUI::LineEdit::setText(std::string text) { _text = text; + repaintEvent(NULL); textChanged(); } diff --git a/plugingui/listbox.cc b/plugingui/listbox.cc new file mode 100644 index 0000000..dfb5f07 --- /dev/null +++ b/plugingui/listbox.cc @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listbox.cc + * + * Mon Feb 25 21:21:41 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "listbox.h" + +#include "painter.h" +#include "font.h" + +#include + +GUI::ListBox::ListBox(GUI::Widget *parent) + : GUI::Widget(parent) +{ + padding = 4; + btn_size = 14; + + scroll_offset = 0; + selected = ""; + + dblclk_handler = NULL; + ptr = NULL; +} + +GUI::ListBox::~ListBox() +{ + // printf("ListBox destroy\n"); +} + +void GUI::ListBox::addItem(std::string name, std::string value) +{ + items[name] = value; + if(selected == "") selected = value; +} + +void GUI::ListBox::clear() +{ + items.clear(); + selected = ""; + scroll_offset = 0; + repaintEvent(NULL); +} + +bool GUI::ListBox::selectItem(std::string name) +{ + if(items.find(name) == items.end()) return false; + selected = items[name]; + repaintEvent(NULL); + return true; +} + +std::string GUI::ListBox::selectedName() +{ + return selected; +} + +std::string GUI::ListBox::selectedValue() +{ + return items[selected]; +} + +void GUI::ListBox::registerDblClickHandler(void (*handler)(void *), void *ptr) +{ + this->dblclk_handler = handler; + this->ptr = ptr; +} + +void GUI::ListBox::repaintEvent(GUI::RepaintEvent *e) +{ + GUI::Painter p(this); + + p.setColour(Colour(0, 0.5)); + p.drawFilledRectangle(0, 0, width() - 1, height() - 1); + + p.setColour(Colour(0.5, 1)); + p.drawRectangle(0, 0, width() - 1, height() - 1); + + int yoffset = padding / 2; + int skip = scroll_offset; + std::map::iterator i = items.begin(); + while(i != items.end()) { + if(skip) { + skip--; + i++; + continue; + } + if(i->second == selected) { + p.setColour(Colour(1, 0.4)); + p.drawFilledRectangle(1, + yoffset - (padding / 2), + width() - 1, + yoffset + (font.textHeight() + 1)); + } + + p.setColour(Colour(1, 1)); + p.drawText(2, yoffset + font.textHeight(), font, i->first); + yoffset += font.textHeight() + padding; + i++; + } + + p.drawRectangle(width() - btn_size, 0, width() - 1, btn_size); + p.drawRectangle(width() - btn_size, height() - btn_size, + width() - 1, height() - 1); +} + +void GUI::ListBox::buttonEvent(ButtonEvent *e) +{ + //printf("click %d %d [dc: %d]\n", e->x, e->y, e->doubleclick); + if(e->direction == 1) { + if(e->x > (width() - btn_size) && e->y < (width() - 1)) { + if(e->y > 0 && e->y < btn_size) { + scroll_offset--; + if(scroll_offset < 0) scroll_offset = 0; + repaintEvent(NULL); + return; + } + + if(e->y > (height() - btn_size) && e->y < (height() - 1)) { + scroll_offset++; + if(scroll_offset > (items.size() - 1)) + scroll_offset = (items.size() - 1); + repaintEvent(NULL); + return; + } + } + + int skip = scroll_offset; + size_t yoffset = padding / 2; + std::map::iterator i = items.begin(); + while(i != items.end()) { + if(skip) { + skip--; + i++; + continue; + } + yoffset += font.textHeight() + padding; + if(e->y < (int)yoffset - (padding / 2)) { + selected = i->second; + break; + } + i++; + } + + repaintEvent(NULL); + + if(e->doubleclick && dblclk_handler) dblclk_handler(ptr); + } +} diff --git a/plugingui/listbox.h b/plugingui/listbox.h new file mode 100644 index 0000000..2a8dc4f --- /dev/null +++ b/plugingui/listbox.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listbox.h + * + * Mon Feb 25 21:21:40 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_LISTBOX_H__ +#define __DRUMGIZMO_LISTBOX_H__ + +#include +#include + +#include "widget.h" +#include "font.h" + +namespace GUI { + +class ListBox : public Widget { +public: + ListBox(Widget *parent); + ~ListBox(); + + bool isFocusable() { return true; } + + void addItem(std::string name, std::string value); + + void clear(); + bool selectItem(std::string name); + std::string selectedName(); + std::string selectedValue(); + + void registerDblClickHandler(void (*handler)(void *), void *ptr); + + virtual void repaintEvent(RepaintEvent *e); + virtual void buttonEvent(ButtonEvent *e); + +private: + std::map items; + std::string selected; + GUI::Font font; + int padding; + int btn_size; + int scroll_offset; + + void (*dblclk_handler)(void *); + void *ptr; +}; + +}; + +#endif/*__DRUMGIZMO_LISTBOX_H__*/ diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h index 9225f28..848a761 100644 --- a/plugingui/nativewindow.h +++ b/plugingui/nativewindow.h @@ -45,6 +45,7 @@ public: virtual void hide() = 0; virtual void handleBuffer() = 0; virtual void redraw() = 0; + virtual void grabMouse(bool grab) = 0; protected: GlobalContext *gctx; diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc index a98ef4c..b1e22c5 100644 --- a/plugingui/nativewindow_win32.cc +++ b/plugingui/nativewindow_win32.cc @@ -52,7 +52,7 @@ GUI::NativeWindowWin32::NativeWindowWin32(GlobalContext *gctx, // object - we need this in the wndproc handler. wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = 0;//class_style; + wcex.style = CS_DBLCLKS;//class_style; wcex.lpfnWndProc = (WNDPROC)dialogProc; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // Set data: @@ -131,4 +131,10 @@ void GUI::NativeWindowWin32::setCaption(const std::string &caption) { } +void GUI::NativeWindowWin32::grabMouse(bool grab) +{ + if(grab) SetCapture(gctx->m_hwnd); + else ReleaseCapture(); +} + #endif/*WIN32*/ diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h index 6039439..cceff2f 100644 --- a/plugingui/nativewindow_win32.h +++ b/plugingui/nativewindow_win32.h @@ -46,6 +46,7 @@ public: void hide(); void handleBuffer(); void redraw(); + void grabMouse(bool grab); private: GUI::Window *window; diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc index 91d7ed6..c7605ef 100644 --- a/plugingui/nativewindow_x11.cc +++ b/plugingui/nativewindow_x11.cc @@ -229,5 +229,11 @@ void GUI::NativeWindowX11::setCaption(const std::string &caption) { } +void GUI::NativeWindowX11::grabMouse(bool grab) +{ + (void)grab; + // Don't need to do anything on this platoform... +} + #endif/*X11*/ diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h index 2e51861..0cd11da 100644 --- a/plugingui/nativewindow_x11.h +++ b/plugingui/nativewindow_x11.h @@ -48,6 +48,7 @@ public: void hide(); void handleBuffer(); void redraw(); + void grabMouse(bool grab); private: ::Window xwindow; diff --git a/plugingui/painter.cc b/plugingui/painter.cc index 025363c..b74952f 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -49,6 +49,107 @@ void GUI::Painter::setColour(Colour colour) this->colour = colour; } +void GUI::Painter::plot(int x, int y, double c) +{ + // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) + + //c += 0.5; + //if(c > 1) c = 1; + + pixbuf->addPixel(x, y, + (unsigned char)(colour.red * 255.0), + (unsigned char)(colour.green * 255.0), + (unsigned char)(colour.blue * 255.0), + (unsigned char)(colour.alpha * 255 * c)); + +} + +#include +double GUI::Painter::ipart(double x) +{ + return floor(x); //integer part of x' +} + +double GUI::Painter::round(double x) +{ + return ipart(x + 0.5); +} + +double GUI::Painter::fpart(double x) +{ + return x - ipart(x);//'fractional part of x' +} + +double GUI::Painter::rfpart(double x) +{ + return 1 - fpart(x); +} + + +#define SWAP(x, y) { int tmp = x; x = y; y = tmp; } +void GUI::Painter::drawLine(int x0, int y0, int x1, int y1) +{ + bool steep = abs(y1 - y0) > abs(x1 - x0); + + if(steep) { + SWAP(x0, y0); + SWAP(x1, y1); + } + if(x0 > x1) { + SWAP(x0, x1); + SWAP(y0, y1); + } + + double dx = x1 - x0; + double dy = y1 - y0; + double gradient = dy / dx; + + // handle first endpoint + double xend = round(x0); + double yend = y0 + gradient * (xend - x0); + double xgap = rfpart(x0 + 0.5); + double xpxl1 = xend; //this will be used in the main loop + double ypxl1 = ipart(yend); + if(steep) { + plot(ypxl1, xpxl1, rfpart(yend) * xgap); + plot(ypxl1+1, xpxl1, fpart(yend) * xgap); + } else { + plot(xpxl1, ypxl1 , rfpart(yend) * xgap); + plot(xpxl1, ypxl1+1, fpart(yend) * xgap); + } + double intery = yend + gradient; // first y-intersection for the main loop + + // handle second endpoint + + xend = round(x1); + yend = y1 + gradient * (xend - x1); + xgap = fpart(x1 + 0.5); + double xpxl2 = xend; //this will be used in the main loop + double ypxl2 = ipart(yend); + if(steep) { + plot(ypxl2 , xpxl2, rfpart(yend) * xgap); + plot(ypxl2+1, xpxl2, fpart(yend) * xgap); + } else { + plot(xpxl2, ypxl2, rfpart(yend) * xgap); + plot(xpxl2, ypxl2+1, fpart(yend) * xgap); + } + + // main loop + for(int x = xpxl1 + 1; x <= xpxl2 - 1; x++) { + if(steep) { + plot(ipart(intery) , x, rfpart(intery)); + plot(ipart(intery)+1, x, fpart(intery)); + } else { + plot(x, ipart (intery), rfpart(intery)); + plot(x, ipart (intery)+1, fpart(intery)); + } + intery += gradient; + } +} +///////////////////////////////////////////// + +/* +// No antialiasing void GUI::Painter::drawLine(int x0, int y0, int x1, int y1) { int dx = abs(x1 - x0); @@ -78,6 +179,7 @@ void GUI::Painter::drawLine(int x0, int y0, int x1, int y1) } } } +*/ void GUI::Painter::drawRectangle(int x1, int y1, int x2, int y2) { @@ -123,6 +225,80 @@ void GUI::Painter::drawPoint(int x, int y) (unsigned char)(colour.alpha * 255.0)); } +#if 0 +static double distance(double r, double y) +{ + double real_point = sqrt(pow(r, 2) - pow(y, 2)); + return ceil(real_point) - real_point; +} + +double new_color(double i) { + return i * 127; +} + +void GUI::Painter::drawCircle(int cx, int cy, double radius) +{ + // wu_circle($image, $r, $color, $offset_x = null, $offset_y = null) { + //$red = $color["red"]; + //$green = $color["green"]; + //$blue = $color["blue"]; + int offset_x = cx; + int offset_y = cy; + int x = radius; + // int xx = radius; + int y = -1; + // int yy = -1; + double t = 0; + //$color = imagecolorallocate($image, $red, $green, $blue); + while(x > y) { + y++; + double current_distance = distance(radius, y); + if(current_distance < t) { + x--; + } + + double trasparency = new_color(current_distance); + double alpha = trasparency; + double alpha2 = 127.0 - trasparency; + + double color = 1; + + plot(x + offset_x, y + offset_y, color); + plot(x + offset_x - 1, y + offset_y, alpha2 ); + plot(x + offset_x + 1, y + offset_y, alpha ); + + plot(y + offset_x, x + offset_y, color); + plot(y + offset_x, x + offset_y - 1, alpha2); + plot(y + offset_x, x + offset_y + 1, alpha); + + plot(offset_x - x , y + offset_y, color); + plot(offset_x - x + 1, y + offset_y, alpha2); + plot(offset_x - x - 1, y + offset_y, alpha); + + plot(offset_x - y, x + offset_y, color); + plot(offset_x - y, x + offset_y - 1, alpha2); + plot(offset_x - y, x + offset_y + 1, alpha); + + plot(x + offset_x, offset_y - y, color); + plot(x + offset_x - 1, offset_y - y, alpha2); + plot(x + offset_x + 1, offset_y - y, alpha); + + plot(y + offset_x, offset_y - x, color); + plot(y + offset_x, offset_y - x - 1, alpha); + plot(y + offset_x, offset_y - x + 1, alpha2); + + plot(offset_x - y, offset_y - x, color); + plot(offset_x - y, offset_y - x - 1, alpha); + plot(offset_x - y, offset_y - x + 1, alpha2); + + plot(offset_x - x, offset_y - y, color); + plot(offset_x - x - 1, offset_y - y, alpha); + plot(offset_x - x + 1, offset_y - y, alpha2); + + t = current_distance; + } +} +#else static void plot4points(GUI::Painter *p, int cx, int cy, int x, int y) { p->drawPoint(cx + x, cy + y); @@ -131,7 +307,7 @@ static void plot4points(GUI::Painter *p, int cx, int cy, int x, int y) if(x != 0 && y != 0) p->drawPoint(cx - x, cy - y); } -void GUI::Painter::drawCircle(int cx, int cy, int radius) +void GUI::Painter::drawCircle(int cx, int cy, double radius) { int error = -radius; int x = radius; @@ -152,6 +328,7 @@ void GUI::Painter::drawCircle(int cx, int cy, int radius) } } } +#endif static void plot4lines(GUI::Painter *p, int cx, int cy, int x, int y) { diff --git a/plugingui/painter.h b/plugingui/painter.h index c9fd60d..b45cf3a 100644 --- a/plugingui/painter.h +++ b/plugingui/painter.h @@ -64,11 +64,17 @@ public: void drawRectangle(int x1, int y1, int x2, int y2); void drawFilledRectangle(int x1, int y1, int x2, int y2); void drawPoint(int x, int y); - void drawCircle(int x, int y, int r); + void drawCircle(int x, int y, double r); void drawFilledCircle(int x, int y, int r); void drawImage(int x, int y, struct __img__ * img); private: + void plot(int x, int y, double c); + double ipart(double x); + double round(double x); + double fpart(double x); + double rfpart(double x); + Widget *widget; PixelBufferAlpha *pixbuf; Colour colour; diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index fb4d05f..e9e376a 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -62,7 +62,7 @@ GUI::PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) { this->idx = ::idx++; buf = NULL; - x = y = 0; + x = y = 10; realloc(width, height); } @@ -84,12 +84,39 @@ void GUI::PixelBufferAlpha::setPixel(size_t x, size_t y, { // printf("%d %d %d %d\n", red, green, blue, alpha); if(x >= width || y >= height) return; + /* + float a = alpha / 255.0; + buf[PX(0)] = (unsigned char)(red * a + buf[PX(0)] * (1-a)); + buf[PX(1)] = (unsigned char)(green * a + buf[PX(1)] * (1-a)); + buf[PX(2)] = (unsigned char)(blue * a + buf[PX(2)] * (1-a)); + buf[PX(3)] = (unsigned char)(alpha * a + buf[PX(3)] * (1-a)); + */ buf[PX(0)] = red; buf[PX(1)] = green; buf[PX(2)] = blue; buf[PX(3)] = alpha; } +void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) +{ + // printf("%d %d %d %d\n", red, green, blue, alpha); + if(x >= width || y >= height) return; + + if(alpha == 0) return; + + float a = (float)alpha / (float)(alpha + buf[PX(3)]); + buf[PX(0)] = (unsigned char)(red * a + buf[PX(0)] * (1-a)); + buf[PX(1)] = (unsigned char)(green * a + buf[PX(1)] * (1-a)); + buf[PX(2)] = (unsigned char)(blue * a + buf[PX(2)] * (1-a)); + + //buf[PX(3)] = (unsigned char)(alpha * a + buf[PX(3)] * (1-a)); + buf[PX(3)] = alpha>buf[PX(3)]?alpha:buf[PX(3)]; +} + void GUI::PixelBufferAlpha::pixel(size_t x, size_t y, unsigned char *red, unsigned char *green, diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 29cda7f..21a6ceb 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -63,6 +63,12 @@ public: unsigned char blue, unsigned char alpha); + void addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); + void pixel(size_t x, size_t y, unsigned char *red, unsigned char *green, diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 09045ab..2aded27 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -30,6 +30,7 @@ #include #include "globalcontext.h" +#include "knob.h" #ifndef STANDALONE #include @@ -56,16 +57,40 @@ void checkClick(void *ptr) Conf::enable_velocity_modifier = gui->check->checked(); } -void sliderChange(void *ptr) +void knobChange(void *ptr) { PluginGUI *gui = (PluginGUI*)ptr; - Conf::velocity_modifier_weight = gui->slider->value(); + Conf::velocity_modifier_weight = gui->knob->value(); } -void sliderChange2(void *ptr) +void knobChange2(void *ptr) { PluginGUI *gui = (PluginGUI*)ptr; - Conf::velocity_modifier_falloff = gui->slider2->value(); + Conf::velocity_modifier_falloff = gui->knob2->value(); +} + +GUI::FileBrowser *fb; +void selectFile(void *ptr, std::string filename) +{ + GUI::LineEdit *le = (GUI::LineEdit *)ptr; + le->setText(filename); + fb->hide(); +} + +void kitBrowseClick(void *ptr) +{ + PluginGUI *gui = (PluginGUI*)ptr; + + fb->registerFileSelectHandler(selectFile, gui->lineedit); + fb->show(); +} + +void midimapBrowseClick(void *ptr) +{ + PluginGUI *gui = (PluginGUI*)ptr; + + fb->registerFileSelectHandler(selectFile, gui->lineedit2); + fb->show(); } void loadKitClick(void *ptr) @@ -152,66 +177,108 @@ void PluginGUI::init() window = new GUI::Window(gctx); window->resize(640, 200); + // Enable Velocity + GUI::Label *lbl_enable = new GUI::Label(window); + lbl_enable->setText("Enable Velocity Modifier"); + lbl_enable->move(97, 81); + lbl_enable->resize(100, 20); + check = new GUI::CheckBox(window); check->move(82,82); check->resize(16,16); check->setChecked(Conf::enable_velocity_modifier); check->registerClickHandler(checkClick, this); - slider = new GUI::Slider(window); - slider->move(100,80); - slider->resize(390, 20); - slider->setValue(Conf::velocity_modifier_weight); - slider->registerClickHandler(sliderChange, this); - - slider2 = new GUI::Slider(window); - slider2->move(100,110); - slider2->resize(390, 20); - slider2->setValue(Conf::velocity_modifier_falloff); - slider2->registerClickHandler(sliderChange2, this); - - lbl = new GUI::Label(window); - lbl->setText("Drumkit:"); - lbl->move(10, 10); - lbl->resize(70, 20); - - led = new GUI::LED(window); - led->move(500,12); - led->resize(16, 16); - // led->setState(false); - - lineedit = new FileLineEdit(window, led); - if(drumgizmo) lineedit->setText(drumgizmo->drumkitfile()); - else lineedit->setText("Missing DrumGizmo*"); - lineedit->move(80, 10); - lineedit->resize(410, 20); - - btn_ok = new GUI::Button(window); - btn_ok->setText("Load Kit"); - btn_ok->move(520, 10); - btn_ok->resize(100, 20); - btn_ok->registerClickHandler(loadKitClick, this); - - lbl2 = new GUI::Label(window); - lbl2->setText("Midimap:"); - lbl2->move(10, 45); - lbl2->resize(70, 20); - - led2 = new GUI::LED(window); - led2->move(500,47); - led2->resize(16, 16); - // led2->setState(false); - - lineedit2 = new FileLineEdit(window, led2); - if(drumgizmo) lineedit2->setText(drumgizmo->midimapfile); - lineedit2->move(80, 45); - lineedit2->resize(410, 20); - - btn_ok2 = new GUI::Button(window); - btn_ok2->setText("Load Map"); - btn_ok2->move(520, 45); - btn_ok2->resize(100, 20); - btn_ok2->registerClickHandler(loadMidimapClick, this); + // Velocity Weight Modifier: + { + int xpos = 180; + GUI::Label *lbl_weight = new GUI::Label(window); + lbl_weight->setText("Weight Modifier"); + lbl_weight->move(xpos, 138); + lbl_weight->resize(100, 20); + + knob = new GUI::Knob(window); + knob->move(xpos + 30, 100); + knob->resize(41, 41); + knob->setValue(Conf::velocity_modifier_weight); + knob->registerClickHandler(knobChange, this); + } + + // Velocity Falloff Modifier: + { + int xpos = 300; + GUI::Label *lbl_falloff = new GUI::Label(window); + lbl_falloff->setText("Falloff Modifier"); + lbl_falloff->move(xpos, 138); + lbl_falloff->resize(100, 20); + + knob2 = new GUI::Knob(window); + knob2->move(xpos + 30, 100); + knob2->resize(41, 41); + knob2->setValue(Conf::velocity_modifier_falloff); + knob2->registerClickHandler(knobChange2, this); + } + + // Drumkit file + { + GUI::Label *lbl = new GUI::Label(window); + lbl->setText("Drumkit:"); + lbl->move(10, 10); + lbl->resize(70, 20); + + led = new GUI::LED(window); + led->move(500,12); + led->resize(16, 16); + // led->setState(false); + + lineedit = new FileLineEdit(window, led); + if(drumgizmo) lineedit->setText(drumgizmo->drumkitfile()); + else lineedit->setText("Missing DrumGizmo*"); + lineedit->move(70, 10); + lineedit->resize(408, 20); + + GUI::Button *btn_brw = new GUI::Button(window); + btn_brw->setText("..."); + btn_brw->move(480, 10); + btn_brw->resize(20, 20); + btn_brw->registerClickHandler(kitBrowseClick, this); + + btn_ok = new GUI::Button(window); + btn_ok->setText("Load Kit"); + btn_ok->move(520, 10); + btn_ok->resize(100, 20); + btn_ok->registerClickHandler(loadKitClick, this); + } + + // Midimap file + { + lbl2 = new GUI::Label(window); + lbl2->setText("Midimap:"); + lbl2->move(10, 45); + lbl2->resize(70, 20); + + led2 = new GUI::LED(window); + led2->move(500,47); + led2->resize(16, 16); + // led2->setState(false); + + lineedit2 = new FileLineEdit(window, led2); + if(drumgizmo) lineedit2->setText(drumgizmo->midimapfile); + lineedit2->move(70, 45); + lineedit2->resize(408, 20); + + GUI::Button *btn_brw = new GUI::Button(window); + btn_brw->setText("..."); + btn_brw->move(480, 45); + btn_brw->resize(20, 20); + btn_brw->registerClickHandler(midimapBrowseClick, this); + + btn_ok2 = new GUI::Button(window); + btn_ok2->setText("Load Map"); + btn_ok2->move(520, 45); + btn_ok2->resize(100, 20); + btn_ok2->registerClickHandler(loadMidimapClick, this); + } btn_cancel = new GUI::Button(window); btn_cancel->setText("Close"); @@ -224,6 +291,13 @@ void PluginGUI::init() lbl3->move(120, 180); lbl3->resize(70, 20); + // Create filebrowser + filebrowser = new GUI::FileBrowser(window); + filebrowser->move(0, 0); + filebrowser->resize(window->width() - 1, window->height() - 1); + filebrowser->hide(); + fb = filebrowser; + window->show(); } @@ -279,6 +353,7 @@ void stop(void *ptr) int main() { +/* hug_status_t status = hug_init(HUG_FLAG_OUTPUT_TO_SYSLOG, HUG_OPTION_SYSLOG_HOST, "192.168.0.10", HUG_OPTION_SYSLOG_PORT, 514, @@ -288,7 +363,7 @@ int main() printf("Error: %d\n", status); return 1; } - +*/ INFO(example, "We are up and running"); bool running = true; diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index 086a8d5..d6ddde3 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -35,7 +35,9 @@ #include "filelineedit.h" #include "checkbox.h" #include "button.h" -#include "slider.h" +#include "knob.h" + +#include "filebrowser.h" #include "thread.h" @@ -63,11 +65,13 @@ public: GUI::Window *window; GUI::EventHandler *eventhandler; + GUI::FileBrowser *filebrowser; + DrumGizmo *drumgizmo; GUI::CheckBox *check; - GUI::Slider *slider; - GUI::Slider *slider2; + GUI::Knob *knob; + GUI::Knob *knob2; GUI::Button *btn_ok; GUI::Button *btn_ok2; diff --git a/plugingui/slider.cc b/plugingui/slider.cc index b58bde9..953c8e6 100644 --- a/plugingui/slider.cc +++ b/plugingui/slider.cc @@ -66,6 +66,10 @@ void GUI::Slider::mouseMoveEvent(MouseMoveEvent *e) { if(state == down) { val = maximum / (float)width() * (float)e->x; + + if(val < 0) val = 0; + if(val > 1) val = 1; + if(handler) handler(ptr); repaintEvent(NULL); } @@ -76,12 +80,20 @@ void GUI::Slider::buttonEvent(ButtonEvent *e) if(e->direction == 1) { state = down; val = maximum / (float)width() * (float)e->x; + + if(val < 0) val = 0; + if(val > 1) val = 1; + if(handler) handler(ptr); repaintEvent(NULL); } if(e->direction == -1) { state = up; val = maximum / (float)width() * (float)e->x; + + if(val < 0) val = 0; + if(val > 1) val = 1; + repaintEvent(NULL); clicked(); if(handler) handler(ptr); @@ -90,7 +102,7 @@ void GUI::Slider::buttonEvent(ButtonEvent *e) void GUI::Slider::repaintEvent(GUI::RepaintEvent *e) { - DEBUG(slider, "Slider::repaintEvent (%f)\n", val); + //DEBUG(slider, "Slider::repaintEvent (%f)\n", val); Painter p(this); diff --git a/plugingui/widget.cc b/plugingui/widget.cc index 4b09732..eb7b0b6 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -27,9 +27,7 @@ #include "widget.h" #include "globalcontext.h" - #include "painter.h" - #include "window.h" #include @@ -37,24 +35,41 @@ GUI::Widget::Widget(Widget *parent) : pixbuf(1, 1) { + _width = _height = 10; + this->parent = parent; if(parent) { parent->addChild(this); _window = parent->window(); } _width = _height = 0; + _visible = true; } GUI::Widget::~Widget() { + if(parent) parent->removeChild(this); } void GUI::Widget::show() { + setVisible(true); } void GUI::Widget::hide() { + setVisible(false); +} + +void GUI::Widget::setVisible(bool v) +{ + _visible = v; + repaintEvent(NULL); +} + +bool GUI::Widget::visible() +{ + return _visible; } void GUI::Widget::addChild(GUI::Widget *widget) @@ -62,6 +77,18 @@ void GUI::Widget::addChild(GUI::Widget *widget) children.push_back(widget); } +void GUI::Widget::removeChild(GUI::Widget *widget) +{ + std::vector::iterator i = children.begin(); + while(i != children.end()) { + if(*i == widget) { + children.erase(i); + return; + } + i++; + } +} + void GUI::Widget::resize(size_t width, size_t height) { _width = width; @@ -73,8 +100,16 @@ void GUI::Widget::move(size_t x, size_t y) { _x = x; _y = y; - pixbuf.x = x; - pixbuf.y = y; + /* + Widget *p = parent; + while(p) { + x += p->pixbuf.x; + y += p->pixbuf.y; + p = p->parent; + } + */ + // pixbuf.x = x; + // pixbuf.y = y; } size_t GUI::Widget::x() { return _x; } @@ -82,14 +117,30 @@ size_t GUI::Widget::y() { return _y; } size_t GUI::Widget::width() { return _width; } size_t GUI::Widget::height() { return _height; } +size_t GUI::Widget::windowX() +{ + size_t window_x = x(); + if(parent) window_x += parent->windowX(); + return window_x; +} + +size_t GUI::Widget::windowY() +{ + size_t window_y = y(); + if(parent) window_y += parent->windowY(); + return window_y; +} + GUI::Widget *GUI::Widget::find(size_t x, size_t y) { - std::vector::iterator i = children.begin(); - while(i != children.end()) { + std::vector::reverse_iterator i = children.rbegin(); + while(i != children.rend()) { Widget *w = *i; - if(w->x() <= x && (w->x() + w->width()) >= x && - w->y() <= y && w->y() + w->height() >= y) - return w->find(x - w->x(), y - w->y()); + if(w->visible()) { + if(w->x() <= x && (w->x() + w->width()) >= x && + w->y() <= y && w->y() + w->height() >= y) + return w->find(x - w->x(), y - w->y()); + } i++; } @@ -104,8 +155,10 @@ GUI::Window *GUI::Widget::window() void GUI::Widget::repaint_r(GUI::RepaintEvent *e) { - Painter p(this); + Painter p(this); // make sure pixbuf refcount is incremented. + repaintEvent(e); + std::vector::iterator i = children.begin(); while(i != children.end()) { Widget *w = *i; @@ -118,13 +171,18 @@ std::vector GUI::Widget::getPixelBuffers() { std::vector pbs; + pixbuf.x = windowX(); + pixbuf.y = windowY(); + pbs.push_back(&pixbuf); std::vector::iterator i = children.begin(); while(i != children.end()) { Widget *w = *i; - std::vector pbs0 = w->getPixelBuffers(); - pbs.insert(pbs.end(), pbs0.begin(), pbs0.end()); + if(w->visible()) { + std::vector pbs0 = w->getPixelBuffers(); + pbs.insert(pbs.end(), pbs0.begin(), pbs0.end()); + } i++; } diff --git a/plugingui/widget.h b/plugingui/widget.h index 6f09533..c0d0a73 100644 --- a/plugingui/widget.h +++ b/plugingui/widget.h @@ -27,10 +27,9 @@ #ifndef __DRUMGIZMO_WIDGET_H__ #define __DRUMGIZMO_WIDGET_H__ -#include - #include "guievent.h" #include "pixelbuffer.h" + #include namespace GUI { @@ -50,6 +49,8 @@ public: virtual size_t x(); virtual size_t y(); + virtual size_t windowX(); + virtual size_t windowY(); virtual size_t width(); virtual size_t height(); @@ -57,6 +58,7 @@ public: virtual bool catchMouse() { return false; } void addChild(Widget *widget); + void removeChild(Widget *widget); virtual void repaintEvent(RepaintEvent *e) {} virtual void mouseMoveEvent(MouseMoveEvent *e) {} @@ -74,11 +76,18 @@ public: bool hasKeyboardFocus(); + Widget *parent; + + bool visible(); + void setVisible(bool visible); + protected: std::vector children; - Widget *parent; Window *_window; size_t _x, _y, _width, _height; + +private: + bool _visible; }; }; diff --git a/plugingui/window.cc b/plugingui/window.cc index bbeffa1..1795d62 100644 --- a/plugingui/window.cc +++ b/plugingui/window.cc @@ -104,6 +104,8 @@ size_t GUI::Window::x() { return _x; } size_t GUI::Window::y() { return _y; } size_t GUI::Window::width() { return _width; } size_t GUI::Window::height() { return _height; } +size_t GUI::Window::windowX() { return 0; } +size_t GUI::Window::windowY() { return 0; } void GUI::Window::show() { @@ -200,5 +202,6 @@ GUI::Widget *GUI::Window::buttonDownFocus() void GUI::Window::setButtonDownFocus(GUI::Widget *widget) { _buttonDownFocus = widget; + native->grabMouse(widget != NULL); // repaint_r(NULL); } diff --git a/plugingui/window.h b/plugingui/window.h index 8e61603..0820b40 100644 --- a/plugingui/window.h +++ b/plugingui/window.h @@ -49,6 +49,8 @@ public: size_t x(); size_t y(); + size_t windowX(); + size_t windowY(); size_t width(); size_t height(); -- cgit v1.2.3