123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /* GCSx
- ** SLIDER.CPP
- **
- ** Numerical slider widget
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program 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.
- **
- ** This program 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 this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- WSlider::WSlider(int sId, int sBegin, int sEnd, int* sSetting, int sLength) : Widget(sId, blankString, sSetting) { start_func
- assert(sBegin <= sEnd);
- assert(sSetting);
- assert((sLength > 0) || (sLength == -1));
-
- if (sLength == -1) pixelLength = GUI_SLIDER_TRACKLENGTH;
- else pixelLength = sLength;
-
- rangeBegin = sBegin;
- rangeEnd = sEnd;
- linkedTo = NULL;
-
- // Tab extends a certain amount past the end of the track
- resize(GUI_SLIDER_TABWIDTH + pixelLength, GUI_SLIDER_TABHEIGHT);
- load(); // Always keep a valid setting in it, due to linkTo
- }
- int WSlider::event(int hasFocus, const SDL_Event* event) { start_func
- assert(event);
- assert(parent);
- switch (event->type) {
- case SDL_INPUTFOCUS:
- if (event->user.code & 1) {
- if (!haveFocus) {
- haveFocus = 1;
- setDirty();
- }
- }
- else {
- if ((haveFocus) || (dragging)) {
- dragging = haveFocus = 0;
- setDirty();
- }
- }
- return 1;
-
- case SDL_KEYDOWN:
- switch (combineKey(event->key.keysym.sym, event->key.keysym.mod)) {
- case SDLK_LEFT:
- case SDLK_UP:
- statePixel(pixelValue - 1);
- return 1;
-
- case SDLK_RIGHT:
- case SDLK_DOWN:
- statePixel(pixelValue + 1);
- return 1;
- case SDLK_PAGEUP:
- statePixel(pixelValue - GUI_SLIDER_TABWIDTH);
- return 1;
- case SDLK_PAGEDOWN:
- statePixel(pixelValue + GUI_SLIDER_TABWIDTH);
- return 1;
- case SDLK_HOME:
- state(rangeBegin);
- return 1;
- case SDLK_END:
- state(rangeEnd);
- return 1;
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- if ((event->button.button == SDL_BUTTON_LEFT) && (dragging)) {
- dragging = 0;
- setDirty();
- }
- return 1;
-
- case SDL_MOUSEBUTTONDBL:
- case SDL_MOUSEBUTTONDOWN:
- if (event->button.button == SDL_BUTTON_LEFT) {
- if (event->button.x < pixelValue) {
- statePixel(pixelValue - GUI_SLIDER_TABWIDTH);
- }
- else if (event->button.x >= pixelValue + GUI_SLIDER_TABWIDTH) {
- statePixel(pixelValue + GUI_SLIDER_TABWIDTH);
- }
- else {
- dragging = 1;
- draggingX = event->button.x;
- draggingValue = pixelValue;
- setDirty();
- }
- return 1;
- }
- else if (event->button.button == SDL_BUTTON_WHEELUP) {
- statePixel(pixelValue - GUI_SLIDER_TABWIDTH);
- return 1;
- }
- else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
- statePixel(pixelValue + GUI_SLIDER_TABWIDTH);
- return 1;
- }
- break;
- case SDL_MOUSEMOTION:
- if (dragging) {
- // Signed required in case negative
- statePixel(draggingValue + ((Sint16)event->motion.x) - draggingX);
- }
- return 1;
- }
-
- return 0;
- }
- void WSlider::linkTo(WNumberBox* linked) { start_func
- if (linked == NULL) {
- linkedTo = NULL;
- }
- else {
- linkedTo = linked;
- linkedTo->state(currentValue);
- }
- }
- void WSlider::siblingModified(Widget* modified) { start_func
- assert(modified);
- assert(modified != this);
-
- if (modified == linkedTo) stateFromLoad(linkedTo->state());
- }
- void WSlider::load() { start_func
- dragging = 0;
- stateFromLoad(*((int*)setting));
- setDirty();
- }
- void WSlider::apply() { start_func
- *((int*)setting) = state();
- }
- void WSlider::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
- assert(destSurface);
- if (visible) {
- // If dirty, redraw all
- if (dirty) {
- getRect(toDisplay);
- toDisplay.x += xOffset;
- toDisplay.y += yOffset;
- dirty = 0;
- intersectRects(toDisplay, clipArea);
- }
-
- // Anything to draw?
- if (toDisplay.w) {
- SDL_SetClipRect(destSurface, &toDisplay);
-
- xOffset += x;
- yOffset += y;
- // This widget makes no attempt at partial redraw other than the initial fill.
- SDL_FillRect(destSurface, &toDisplay, guiPacked[COLOR_FILL]);
-
- // The track is extended in total length by the tracksize, to make
- // the appearance balanced
- drawGuiBoxInvert(xOffset + GUI_SLIDER_TABWIDTH / 2 - GUI_SLIDER_TRACKSIZE / 2, yOffset + GUI_SLIDER_TABHEIGHT / 2 - GUI_SLIDER_TRACKSIZE / 2, pixelLength + GUI_SLIDER_TRACKSIZE, GUI_SLIDER_TRACKSIZE, 1, destSurface);
-
- // The tab is centered on it's pixel; 0 is actually one pixel off the tracksize,
- // lining up with the left center pixel of the tab (since the tab is an even
- // width) This creates a balanced appearance from 0 to pixelLength.
- // It is drawn inverted if currently depressed.
- if (dragging) {
- drawRect(xOffset + pixelValue, yOffset, GUI_SLIDER_TABWIDTH, GUI_SLIDER_TABHEIGHT, guiPacked[COLOR_FILL], destSurface);
- drawGuiBoxInvert(xOffset + pixelValue, yOffset, GUI_SLIDER_TABWIDTH, GUI_SLIDER_TABHEIGHT, 2, destSurface);
- }
- else {
- drawGuiBox(xOffset + pixelValue, yOffset, GUI_SLIDER_TABWIDTH, GUI_SLIDER_TABHEIGHT, 2, destSurface);
- }
-
- // Focus?
- if (haveFocus) drawFocusBox(xOffset, yOffset, width, height, destSurface);
-
- // This widget has no special disabled appearance.
- }
- }
- }
- int WSlider::state() const { start_func
- return currentValue;
- }
- int WSlider::state(int newValue) { start_func
- int markDirty = 0;
- if (newValue != currentValue) markDirty = 1;
-
- stateFromLoad(newValue);
- if ((markDirty) && (linkedTo)) linkedTo->state(newValue);
-
- // May not have a parent, as this is called during constructor
- if (parent) parent->childModified(this);
- return currentValue;
- }
- int WSlider::stateFromLoad(int newValue) { start_func
- if (newValue < rangeBegin) newValue = rangeBegin;
- else if (newValue > rangeEnd) newValue = rangeEnd;
- int markDirty = 0;
- if (newValue != currentValue) markDirty = 1;
- currentValue = newValue;
-
- if (rangeEnd == rangeBegin) {
- pixelValue = pixelLength;
- }
- else {
- // sBegin will always result in 0
- // sEnd will always result in pixelLength
- // values in between are equally spaced
- // *2, +1, /2 allows for rounding off
- pixelValue = ((newValue - rangeBegin) * pixelLength * 2 / (rangeEnd - rangeBegin) + 1) / 2;
- }
-
- if (markDirty) {
- setDirty();
- }
- return currentValue;
- }
- int WSlider::statePixel(int newPixel) { start_func
- if (newPixel < 0) newPixel = 0;
- else if (newPixel > pixelLength) newPixel = pixelLength;
-
- if (newPixel != pixelValue) {
- // *2, +1, /2 allows for rounding off
- return state(rangeBegin + (newPixel * (rangeEnd - rangeBegin) * 2 / pixelLength + 1) / 2);
- }
- return state();
- }
|