From abc0caf95536a4001615f863860a091d6bc55973 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 19 Apr 2013 22:57:02 +0200 Subject: New listbox widgets and scrollbar. --- plugingui/listbox.cc | 5 ++ plugingui/listbox.h | 1 + plugingui/listboxbasic.cc | 118 ++++++++++++++++-------------- plugingui/listboxbasic.h | 21 ++++-- plugingui/listboxthin.cc | 118 ++++++++++++++++++++++++++++++ plugingui/listboxthin.h | 67 +++++++++++++++++ plugingui/scrollbar.cc | 182 ++++++++++++++++++++++++++++++++++++++++++++++ plugingui/scrollbar.h | 75 +++++++++++++++++++ 8 files changed, 527 insertions(+), 60 deletions(-) create mode 100644 plugingui/listboxthin.cc create mode 100644 plugingui/listboxthin.h create mode 100644 plugingui/scrollbar.cc create mode 100644 plugingui/scrollbar.h diff --git a/plugingui/listbox.cc b/plugingui/listbox.cc index 6c6c6e7..3647753 100644 --- a/plugingui/listbox.cc +++ b/plugingui/listbox.cc @@ -57,6 +57,11 @@ void GUI::ListBox::addItem(std::string name, std::string value) basic->addItem(name, value); } +void GUI::ListBox::addItems(std::vector &items) +{ + basic->addItems(items); +} + void GUI::ListBox::clear() { basic->clear(); diff --git a/plugingui/listbox.h b/plugingui/listbox.h index 9a702df..4a7af20 100644 --- a/plugingui/listbox.h +++ b/plugingui/listbox.h @@ -42,6 +42,7 @@ public: ~ListBox(); void addItem(std::string name, std::string value); + void addItems(std::vector &items); void clear(); bool selectItem(int index); diff --git a/plugingui/listboxbasic.cc b/plugingui/listboxbasic.cc index 25b3daf..25cf00d 100644 --- a/plugingui/listboxbasic.cc +++ b/plugingui/listboxbasic.cc @@ -30,14 +30,25 @@ #include "font.h" #include +#include + +void scrolled(void *ptr) +{ + GUI::ListBoxBasic *l = (GUI::ListBoxBasic *)ptr; + l->repaintEvent(NULL); +} GUI::ListBoxBasic::ListBoxBasic(GUI::Widget *parent) - : GUI::Widget(parent) + : GUI::Widget(parent), scroll(this), bg_img(":widget_c.png") { + scroll.move(0,0); + scroll.resize(18, 100); + + scroll.registerValueChangeHandler(scrolled, this); + padding = 4; - btn_size = 14; + btn_size = 18; - scroll_offset = 0; selected = -1; marked = -1; @@ -49,13 +60,10 @@ GUI::ListBoxBasic::ListBoxBasic(GUI::Widget *parent) valch_handler = NULL; valch_ptr = NULL; - - bg_img = new GUI::Image(":widget_c.png"); } GUI::ListBoxBasic::~ListBoxBasic() { - delete bg_img; } void GUI::ListBoxBasic::setSelection(int index) @@ -66,11 +74,25 @@ void GUI::ListBoxBasic::setSelection(int index) void GUI::ListBoxBasic::addItem(std::string name, std::string value) { - struct item i; - i.name = name; - i.value = value; - - items.push_back(i); + std::vector items; + GUI::ListBoxBasic::Item item; + item.name = name; + item.value = value; + items.push_back(item); + addItems(items); +} + +void GUI::ListBoxBasic::addItems(std::vector &is) +{ + std::vector::iterator i = is.begin(); + while(i != is.end()) { + items.push_back(*i); + i++; + } + + int numitems = height() / (font.textHeight() + padding); + scroll.setRange(numitems); + scroll.setMaximum(items.size()); // sort for(int x = 0; x < (int)items.size() - 1; x++) { @@ -80,7 +102,7 @@ void GUI::ListBoxBasic::addItem(std::string name, std::string value) if(x == selected) setSelection(y); else if(selected == y) setSelection(x); - struct item tmp = items[x]; + GUI::ListBoxBasic::Item tmp = items[x]; items[x] = items[y]; items[y] = tmp; } @@ -94,7 +116,7 @@ void GUI::ListBoxBasic::clear() { items.clear(); setSelection(-1); - scroll_offset = 0; + scroll.setValue(0); repaintEvent(NULL); } @@ -147,45 +169,39 @@ void GUI::ListBoxBasic::repaintEvent(GUI::RepaintEvent *e) int h = height(); if(w == 0 || h == 0) return; - p.drawImageStretched(0, 0, bg_img, w, h); + p.drawImageStretched(0, 0, &bg_img, w, h); + + p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); int yoffset = padding / 2; - int skip = scroll_offset; + int skip = scroll.value(); for(int idx = skip; idx < (int)items.size(); idx++) { - struct item *i = &items[idx]; + GUI::ListBoxBasic::Item *i = &items[idx]; if(idx == selected) { - p.setColour(Colour(0.6, 0.9)); - p.drawFilledRectangle(1, + p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 0.5)); + p.drawFilledRectangle(0, yoffset - (padding / 2), width() - 1, yoffset + (font.textHeight() + 1)); } if(idx == marked) { - p.setColour(Colour(1, 0.9)); - p.drawRectangle(1, + p.drawRectangle(0, yoffset - (padding / 2), width() - 1, yoffset + (font.textHeight() + 1)); } - p.setColour(Colour(1, 1)); + p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + p.drawText(2, yoffset + font.textHeight(), font, i->name); yoffset += font.textHeight() + padding; } - - p.drawRectangle(width() - btn_size, 0, width() - 1, btn_size); - p.drawRectangle(width() - btn_size, height() - btn_size, - width() - 1, height() - 1); } void GUI::ListBoxBasic::scrollEvent(ScrollEvent *e) { - scroll_offset += e->delta; - if(scroll_offset < 0) scroll_offset = 0; - if(scroll_offset > ((int)items.size() - 1)) - scroll_offset = ((int)items.size() - 1); - repaintEvent(NULL); + scroll.scrollEvent(e); } void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e) @@ -198,9 +214,8 @@ void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e) marked--; if(marked < 0) marked = 0; - if(marked < scroll_offset) { - scroll_offset = marked; - if(scroll_offset < 0) scroll_offset = 0; + if(marked < scroll.value()) { + scroll.setValue(marked); } } break; @@ -212,18 +227,15 @@ void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e) marked++; if(marked > ((int)items.size() - 1)) marked = (int)items.size() - 1; - if(marked > (scroll_offset + numitems - 1)) { - scroll_offset = marked - numitems + 1; - if(scroll_offset > ((int)items.size() - 1)) - scroll_offset = ((int)items.size() - 1); + if(marked > (scroll.value() + numitems - 1)) { + scroll.setValue(marked - numitems + 1); } } break; case GUI::KeyEvent::KEY_HOME: marked = 0; - if(marked < scroll_offset) { - scroll_offset = marked; - if(scroll_offset < 0) scroll_offset = 0; + if(marked < scroll.value()) { + scroll.setValue(marked); } break; case GUI::KeyEvent::KEY_END: @@ -232,10 +244,8 @@ void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e) int numitems = height() / (font.textHeight() + padding); marked = (int)items.size() - 1; - if(marked > (scroll_offset + numitems - 1)) { - scroll_offset = marked - numitems + 1; - if(scroll_offset > ((int)items.size() - 1)) - scroll_offset = ((int)items.size() - 1); + if(marked > (scroll.value() + numitems - 1)) { + scroll.setValue(marked - numitems + 1); } } break; @@ -261,24 +271,19 @@ void GUI::ListBoxBasic::buttonEvent(ButtonEvent *e) if(e->x > ((int)width() - btn_size) && e->y < ((int)width() - 1)) { if(e->y > 0 && e->y < btn_size) { if(e->direction == -1) return; - scroll_offset--; - if(scroll_offset < 0) scroll_offset = 0; - repaintEvent(NULL); + scroll.setValue(scroll.value() - 1); return; } if(e->y > ((int)height() - btn_size) && e->y < ((int)height() - 1)) { if(e->direction == -1) return; - scroll_offset++; - if(scroll_offset > ((int)items.size() - 1)) - scroll_offset = ((int)items.size() - 1); - repaintEvent(NULL); + scroll.setValue(scroll.value() + 1); return; } } if(e->direction == -1) { - int skip = scroll_offset; + int skip = scroll.value(); size_t yoffset = padding / 2; for(int idx = skip; idx < (int)items.size(); idx++) { yoffset += font.textHeight() + padding; @@ -294,7 +299,7 @@ void GUI::ListBoxBasic::buttonEvent(ButtonEvent *e) } if(e->direction != -1) { - int skip = scroll_offset; + int skip = scroll.value(); size_t yoffset = padding / 2; for(int idx = skip; idx < (int)items.size(); idx++) { yoffset += font.textHeight() + padding; @@ -309,3 +314,10 @@ void GUI::ListBoxBasic::buttonEvent(ButtonEvent *e) if(e->doubleclick && sel_handler) sel_handler(sel_ptr); } + +void GUI::ListBoxBasic::resize(int w, int h) +{ + GUI::Widget::resize(w,h); + scroll.move(w - scroll.width(), 0); + scroll.resize(scroll.width(), h); +} diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h index 1b7644e..ebb46b0 100644 --- a/plugingui/listboxbasic.h +++ b/plugingui/listboxbasic.h @@ -34,16 +34,25 @@ #include "font.h" #include "painter.h" +#include "scrollbar.h" + namespace GUI { class ListBoxBasic : public Widget { public: + class Item { + public: + std::string name; + std::string value; + }; + ListBoxBasic(Widget *parent); ~ListBoxBasic(); bool isFocusable() { return true; } void addItem(std::string name, std::string value); + void addItems(std::vector &items); void clear(); bool selectItem(int index); @@ -58,24 +67,22 @@ public: virtual void buttonEvent(ButtonEvent *e); virtual void scrollEvent(ScrollEvent *e); virtual void keyEvent(KeyEvent *e); + virtual void resize(int w, int h); private: - Image *bg_img; + ScrollBar scroll; + + Image bg_img; void setSelection(int index); - struct item { - std::string name; - std::string value; - }; + std::vector items; - std::vector items; int selected; int marked; GUI::Font font; int padding; int btn_size; - int scroll_offset; void (*sel_handler)(void *); void *sel_ptr; diff --git a/plugingui/listboxthin.cc b/plugingui/listboxthin.cc new file mode 100644 index 0000000..3f0fbc6 --- /dev/null +++ b/plugingui/listboxthin.cc @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxthin.cc + * + * Sun Apr 7 19:39:36 CEST 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 "listboxthin.h" + +#include "painter.h" +#include "font.h" + +#include + +GUI::ListBoxThin::ListBoxThin(GUI::Widget *parent) + : GUI::Widget(parent) +{ + box.topLeft = new Image(":thinlistbox_tl.png"); + box.top = new Image(":thinlistbox_t.png"); + box.topRight = new Image(":thinlistbox_tr.png"); + box.left = new Image(":thinlistbox_l.png"); + box.right = new Image(":thinlistbox_r.png"); + box.bottomLeft = new Image(":thinlistbox_bl.png"); + box.bottom = new Image(":thinlistbox_b.png"); + box.bottomRight = new Image(":thinlistbox_br.png"); + box.center = new Image(":thinlistbox_c.png"); + + basic = new GUI::ListBoxBasic(this); + basic->move(box.left->width(), box.top->height()); +} + +GUI::ListBoxThin::~ListBoxThin() +{ +} + +void GUI::ListBoxThin::addItem(std::string name, std::string value) +{ + basic->addItem(name, value); +} + +void GUI::ListBoxThin::addItems(std::vector &items) +{ + basic->addItems(items); +} + +void GUI::ListBoxThin::clear() +{ + basic->clear(); +} + +bool GUI::ListBoxThin::selectItem(int index) +{ + return basic->selectItem(index); +} + +std::string GUI::ListBoxThin::selectedName() +{ + return basic->selectedName(); +} + +std::string GUI::ListBoxThin::selectedValue() +{ + return basic->selectedValue(); +} + +void GUI::ListBoxThin::registerClickHandler(void (*handler)(void *), void *ptr) +{ + basic->registerClickHandler(handler, ptr); +} + +void GUI::ListBoxThin::registerSelectHandler(void (*handler)(void *), void *ptr) +{ + basic->registerSelectHandler(handler, ptr); +} + +void GUI::ListBoxThin::registerValueChangeHandler(void (*handler)(void *), + void *ptr) +{ + basic->registerValueChangeHandler(handler, ptr); +} + +void GUI::ListBoxThin::repaintEvent(GUI::RepaintEvent *e) +{ + GUI::Painter p(this); + + p.clear(); + + int w = width(); + int h = height(); + if(w == 0 || h == 0) return; + p.drawBox(0, 0, &box, w, h); +} + +void GUI::ListBoxThin::resize(int width, int height) +{ + GUI::Widget::resize(width, height); + basic->resize(width - (box.left->width() + box.right->width()), + height - (box.top->height() + box.bottom->height())); +} diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h new file mode 100644 index 0000000..9c5363a --- /dev/null +++ b/plugingui/listboxthin.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxthin.h + * + * Sun Apr 7 19:39:35 CEST 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_LISTBOXTHIN_H__ +#define __DRUMGIZMO_LISTBOXTHIN_H__ + +#include +#include + +#include "widget.h" +#include "painter.h" +#include "listboxbasic.h" + +namespace GUI { + +class ListBoxThin : public Widget { +public: + ListBoxThin(Widget *parent); + ~ListBoxThin(); + + void addItem(std::string name, std::string value); + void addItems(std::vector &items); + + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + + void registerSelectHandler(void (*handler)(void *), void *ptr); + void registerClickHandler(void (*handler)(void *), void *ptr); + void registerValueChangeHandler(void (*handler)(void *), void *ptr); + + virtual void repaintEvent(GUI::RepaintEvent *e); + virtual void resize(int w, int h); + +private: + ListBoxBasic *basic; + + Painter::Box box; +}; + +}; + +#endif/*__DRUMGIZMO_LISTBOXTHIN_H__*/ diff --git a/plugingui/scrollbar.cc b/plugingui/scrollbar.cc new file mode 100644 index 0000000..3fc3ac8 --- /dev/null +++ b/plugingui/scrollbar.cc @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * scrollbar.cc + * + * Sun Apr 14 12:54:58 CEST 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 "scrollbar.h" + +#include + +#include "painter.h" + +GUI::ScrollBar::ScrollBar(GUI::Widget *parent) + : GUI::Widget(parent), bg_img(":widget_c.png") +{ + handler = NULL; + ptr = NULL; +} + +void GUI::ScrollBar::setRange(int r) +{ + DEBUG(scroll, "%d\n", r); + ran = r; + setValue(value()); + repaintEvent(NULL); +} + +int GUI::ScrollBar::range() +{ + return ran; +} + +void GUI::ScrollBar::setMaximum(int m) +{ + DEBUG(scroll, "%d\n", m); + max = m; + setValue(value()); + repaintEvent(NULL); +} + +int GUI::ScrollBar::maximum() +{ + return max; +} + +void GUI::ScrollBar::setValue(int value) +{ + val = value; + if(val > max - ran) val = max - ran; + if(val < 0) val = 0; + + if(handler) handler(ptr); + + repaintEvent(NULL); +} + +int GUI::ScrollBar::value() +{ + return val; +} + +void GUI::ScrollBar::registerValueChangeHandler(void (*handler)(void *), + void *ptr) +{ + this->handler = handler; + this->ptr = ptr; +} + +static void drawArrow(GUI::Painter &p, int x, int y, int w, int h) +{ + if(h < 0) y -= h; + + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); + + y++; + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); +} + +void GUI::ScrollBar::repaintEvent(RepaintEvent *e) +{ + GUI::Painter p(this); + + p.clear(); + + p.drawImageStretched(0, 0, &bg_img, width(), height()); + + p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + if(!max) return; + + { + int h = height() - 2 * width() - 3; + int offset = width() + 2; + + int y_val1 = (val * h) / max; + int y_val2 = ((val + ran) * h) / max; + + p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset); + } + + p.drawLine(0, 0, 0, height()); + + drawArrow(p, width()/4, width()/4, width()/2, -1 * (width()/3)); + p.drawLine(0, width(), width(), width()); + + drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3); + p.drawLine(0, height() - width(), width(), height() - width()); +} + +void GUI::ScrollBar::scrollEvent(ScrollEvent *e) +{ + setValue(value() + e->delta); +} + +void GUI::ScrollBar::mouseMoveEvent(MouseMoveEvent *e) +{ + if(!dragging) return; + + float delta = yoffset - e->y; + + int h = height() - 2 * width() - 3; + delta /= (float)h / (float)max; + setValue(value_offset - delta); +} + +void GUI::ScrollBar::buttonEvent(ButtonEvent *e) +{ + if(e->y < (int)width() && e->y > 0) { + if(e->direction == -1) setValue(value() - 1); + return; + } + + if(e->y > (int)height() - (int)width() && e->y < (int)height()) { + if(e->direction == -1) setValue(value() + 1); + return; + } + + if(e->direction == 1) { + yoffset = e->y; + value_offset = value(); + } + + dragging = (e->direction == 1); +} + +#ifdef TEST_SCROLLBAR +//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_SCROLLBAR*/ diff --git a/plugingui/scrollbar.h b/plugingui/scrollbar.h new file mode 100644 index 0000000..52acf9d --- /dev/null +++ b/plugingui/scrollbar.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * scrollbar.h + * + * Sun Apr 14 12:54:58 CEST 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_SCROLLBAR_H__ +#define __DRUMGIZMO_SCROLLBAR_H__ + +#include "widget.h" +#include "image.h" + +namespace GUI { + +class ScrollBar : public Widget { +public: + ScrollBar(Widget *parent); + + bool catchMouse() { return true; } + + void setRange(int range); + int range(); + + void setMaximum(int max); + int maximum(); + + void setValue(int value); + int value(); + + void registerValueChangeHandler(void (*handler)(void *), void *ptr); + + void repaintEvent(RepaintEvent *e); + void scrollEvent(ScrollEvent *e); + void buttonEvent(ButtonEvent *e); + void mouseMoveEvent(MouseMoveEvent *e); + +private: + int max; + int val; + int ran; + + int yoffset; + int value_offset; + bool dragging; + + Image bg_img; + + void (*handler)(void *); + void *ptr; +}; + +}; + + +#endif/*__DRUMGIZMO_SCROLLBAR_H__*/ -- cgit v1.2.3