/** * Yudit Unicode Editor Source File * * GNU Copyright (C) 1997-2006 Gaspar Sinai * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * dated June 1991. See file COPYYING for details. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "swidget/SSlider.h" /** * This component is used just to draw the slider pattern. */ SSliderComponent::SSliderComponent (void) : lighter ("white"), darker ("black") { lighter = SColor (background.lighter()); darker = SColor (background.darker()); /* this is the minimum size we have */ preferredSize = SDimension (30, 30); } SSliderComponent::~SSliderComponent() { } void SSliderComponent::redraw(SWindow* w, int x, int y, unsigned int width ,unsigned int height) { redraw (w); } void SSliderComponent::redraw(SWindow* w) { int o = 0; int x = getLocation().x; int y = getLocation().y; int width = getSize().width; int height = getSize().height; w->bitfill (background, x, y, (int)getSize().width, (int)getSize().height); for (int j=y + 2; jbitpoint (c, i, j); } } w->bitline (lighter, x+1, y, x+width-2, y); w->bitline (lighter, x, y, x, y+height-2); //w->bitline (lighter, x, y, x, y+height-1); //w->bitline (darker, x, y+1, x, y+height-2); //w->bitline (lighter, x+1, y+1, x+1, y+height-2); w->bitline (darker, x+width-1, y+1, x+width-1, y+height-1); w->bitline (darker, x+1, y+height-1, x+width-2, y+height-1); } void SSliderComponent::setBackground (const SColor& bg) { SComponent::setBackground(bg); lighter = background.lighter(); darker = background.darker(); } /** * This is a real window slider. */ SSlider::SSlider (void) : sliderBackground((unsigned char) 73, (unsigned char) 121, (unsigned char) 134, (unsigned char) 255), border (SBorder::IN) { listener = 0; /* value, step, page, max */ set (SLocation (0,0), SDimension (0,0), SDimension (1,1), SDimension (0,0)); slider.move (SLocation((int)border.getBorderSize().width, (int)border.getBorderSize().height)); clip (true); window->resize(2,2); dragOK = false; setSliderBackground (sliderBackground); } SSlider::~SSlider () { } void SSlider::redraw(SWindow* w, int x, int y, unsigned int width ,unsigned int height) { //fprintf (stderr, "redraw: %d %d %u %u\n", x, y, width ,height); clip (false); border.redraw (w, x, y, width, height); clip (true); slider.redraw (w); } void SSlider::resize (const SDimension& d) { if (getSize() == d) return; SPanel::resize (d); border.resize (d); SDimension td; if (size.width > border.getBorderSize().width * 2) { td.width = size.width - border.getBorderSize().width * 2; } if (size.height > border.getBorderSize().height * 2) { td.height = size.height - border.getBorderSize().height * 2; } clip (true); //slider.resize (td); /* we are a panel */ recalculateGeometry (); window->redraw(true, 0, 0, size.width, size.height); } /** * Turn clipping at the border on and off. * @param on is true if we turn on clipping. */ void SSlider::clip (bool on) { if (!on) { window->removeClippingArea (); return; } window->setClippingArea ( (int) border.getBorderSize().width , (int) border.getBorderSize().height, size.width - 2 * border.getBorderSize().width, size.height - 2 * border.getBorderSize().height); } void SSlider::setBackground (const SColor& bg) { border.setBackground (bg); } void SSlider::setSliderBackground (const SColor& bg) { sliderBackground = bg; window->setBackground (sliderBackground.darker().darker()); slider.setBackground (sliderBackground); } void SSlider::buttonPressed (SWindow * w, int button, int x, int y) { /* drag point is the difference betwen real location is drag location */ SLocation l (x,y); dragPoint = slider.getLocation() - l; dragOK = true; /* see if we clicked the slider */ if (l < slider.getLocation()) { //fprintf (stderr, "1: dragPoint=%d,%d slider=%d,%d\n", // l.x, l.y, slider.getLocation().x, slider.getLocation().y); dragOK = false; page (-1); } if (l > slider.getLocation() + slider.getSize()) { //fprintf (stderr, "2: dragPoint=%d,%d slider=%d,%d %u %u\n", // l.x, l.y, slider.getLocation().x, slider.getLocation().y, // slider.getSize().width, slider.getSize().height); dragOK = false; page (1); } } void SSlider::buttonReleased (SWindow * w, int button, int x, int y) { } void SSlider::buttonDragged (SWindow * w, int button, int x, int y) { if (!dragOK) return; SLocation l = SLocation (x,y) + dragPoint; l = l.minimize (SLocation (0,0)); /* how much is it in value? */ SDimension estate = getSize() - (border.getBorderSize() * 2); SDimension sliderSize = slider.getSize (); SDimension gmax = estate - sliderSize; SLocation newValue = (l * slidable.max) / gmax; newValue = newValue.minimize(SLocation (0,0)).maximize(slidable.max); if (newValue == slidable.value) return; //fprintf (stderr, "old=%d,%d new=%d,%d\n", // value.x, value.y, newValue.x, newValue.y); slidable.value = newValue; slide (true); } /** * page up (positive) or page down (negative) */ void SSlider::page (int count) { SLocation newValue = slidable.value + slidable.page * count; newValue = newValue.minimize(SLocation (0,0)).maximize(slidable.max); if (newValue == slidable.value) return; //fprintf (stderr, "old=%d,%d new=%d,%d\n", // value.x, value.y, newValue.x, newValue.y); slidable.value = newValue; slide (true); } /** * Set these slider properties. * @param _value is the slider value. * @param _step is the single click step. * @param _page is the double click step. * @param _max is the maximum value * @param _vertical is true if vertical values will be set. */ void SSlider::set (int _value, unsigned int _step, unsigned int _page, unsigned int _max, bool _vertical) { if (_step==0 && _page==0 && _max==0) { slide (_value, _vertical); return; } slidable.step = (_vertical) ? SDimension (slidable.step.width, _step) : SDimension (_step, slidable.step.height); slidable.page = (_vertical) ? SDimension (slidable.page.width, _page) : SDimension (_page, slidable.page.height); slidable.max = (_vertical) ? SDimension (slidable.max.width, _max) : SDimension (_max, slidable.max.height); SLocation newValue = (_vertical) ? SLocation (slidable.value.x, _value) : SLocation (_value, slidable.value.y); slidable.value = newValue; recalculateGeometry(); } void SSlider::set (const SLocation& _value, const SDimension& _step, const SDimension & _page, const SDimension& _max) { slidable.value = _value; slidable.step = _step; slidable.page = _page; slidable.max = _max; recalculateGeometry(); } /** * recalculate the slider geometry */ void SSlider::recalculateGeometry () { if (slidable.page == SDimension(0,0)) slidable.page = SDimension (1,1); /* calculate the scale and the slider dimensions */ SDimension estate = getSize() - (border.getBorderSize() * 2); /* This is what we would like to have */ /* max + page = estate ; page = estate - max */ SDimension mestate = slidable.max + slidable.page; SDimension sliderSize = (estate * slidable.page) / mestate; SDimension sliderPrefers = slider.getPreferredSize (); /* this is what geometrically possoble to have */ sliderSize = sliderSize.minimize (sliderPrefers).maximize (estate); /* this is out geometrically possible max. */ SDimension gmax = estate - sliderSize; SLocation sliderLocation = (slidable.value * gmax) / slidable.max; setSliderGeometry (sliderLocation + border.getBorderSize(), sliderSize); } /** * there is no geometry change. just scroll. */ void SSlider::slide (int _value, bool _vertical) { SLocation newValue = (_vertical) ? SLocation (slidable.value.x, _value) : SLocation (_value, slidable.value.y); if (newValue == slidable.value) return; slidable.value = newValue; slide (false); } /** * 2 d slide */ void SSlider::slide (const SLocation& _value) { if (_value == slidable.value) return; slide (false); } void SSlider::slide (bool notify) { slidable.value = slidable.value.maximize (slidable.max).minimize (SLocation(0,0)); SDimension estate = getSize() - (border.getBorderSize() * 2); SDimension sliderSize = slider.getSize (); SDimension gmax = estate - sliderSize; SLocation sliderLocation = (slidable.value * gmax) / slidable.max; setSliderGeometry (sliderLocation + border.getBorderSize(), sliderSize); if (notify && listener) { listener->valueChanged (&slidable, SSliderListener::SS_BOTH); } } /** * Set the slide geometry and redraw slider if necessary. */ void SSlider::setSliderGeometry (SLocation l, SDimension d) { SDimension ssize = slider.getSize (); SLocation sloc = slider.getLocation (); if (l==sloc && d ==ssize) return; SLocation smax = sloc+ssize; /* find the biggest containing rectangle */ SLocation minl = sloc; minl = minl.minmerge (l); SLocation lpd = l+d; SLocation maxl = smax; maxl.maxmerge (lpd); window->copy (sloc.x, sloc.y, d.width, d.height, l.x, l.y); SLocation delta = maxl-minl; /* clear upper */ if (minl.y < l.y && delta.x >0) { SLocation ll = l - minl; window->clear (minl.x, minl.y, delta.x, ll.y); } /* clear lower */ if (maxl.y > lpd.y && delta.x >0) { SLocation lu = maxl - lpd; window->clear (minl.x, lpd.y, delta.x, lu.y); } /* clear left */ if (minl.x < l.x && delta.y >0) { SLocation ll = l - minl; window->clear (minl.x, minl.y, ll.x, delta.y); } /* clear right */ if (maxl.y > lpd.y && delta.x >0) { SLocation lu = maxl - lpd; window->clear (lpd.x, minl.y, lu.x, delta.y); } slider.move (l); if (ssize != d) { slider.resize (d); slider.redraw (window); } } SLocation SSlider::getValue() const { return SLocation (slidable.value); } /** * This is called by a slibadle and it shows that vales have been changed. */ void SSlider::valueChanged (SSlidable* _slidable, SSlideType _type) { switch (_type) { case SSliderListener::SS_HORIZONTAL: set (_slidable->value.x, _slidable->step.width, _slidable->page.width, _slidable->max.width, false); break; case SSliderListener::SS_VERTICAL: set (_slidable->value.y, _slidable->step.height, _slidable->page.height, _slidable->max.height, true); break; case SSliderListener::SS_BOTH: set (_slidable->value, _slidable->step, _slidable->page, _slidable->max); break; } } /** * @param l is the listener. */ SSlidable* SSlider::setSliderListener (SSliderListener* l) { listener = l; return &slidable; }