/** * Dragger * Copyright 2014 by James Brink * Revised date; 4/3/2014 */ // ******************************************************* // Global fields int scrollW_, scrollH_; // Max size of scrolled window normall // equals width and height except when ScrollSketch used // ******************************************************* /** * The Dragger class handles drags on many Clickable objects * in such a way that it is possible to drag non-Clickable * points. Only one Dragger is needed per sketch as only * one item can be dragged at a time. The Dragger is given * a list of Clickable items. When mouse is pressed, the * Dragger determines if cursor is over any of the objects * in that list. * Dragger allows dragging * 1. a Clickable item. * 2. any point designated by that object. */ class Dragger { int trackX, trackY; // The starting location of the designated point. int updatedX, updatedY; // The current location of that point. int startCursorX, startCursorY; // Location of cursor when mouse pressed. int rptX, rptY, rptW, rptH; // The rectangle restricting the updated point. int outsideLimit; // How far outside the rectangle the cursor can move // before the drag is terminated. int minForDrag; // How far the cursor must move before a drag is initiated. // This is to prevent accidenal drags when clicking. Clickable itemTracked; // The clickable item being tracked. This item is // is from the draggable list. Clickable subItemTracked; // The clickable item actually used. Normally // the same as itemTracked but allows for compound items like // ScrollSketch where item tracked is the ScrollSketch and // subItemTracked is the actual ScrollBar currently being // tracked. Clickable[] draggableList; // A list of items that could be tracked. boolean dragging; // Something currently is being dragged. boolean wasDragging; // Something was being or is being dragged. /** * A constructor that includes the list of items that could be dragged. * The list should set so the "top" item, the one drawn last, should be * the last item in the list. That is it should be in the same order * that the Clickable Group is ordered. */ Dragger (Clickable[] draggableArray) { draggableList = draggableArray; outsideLimit = 100; minForDrag = 4; dragging = false; wasDragging = false; itemTracked = null; subItemTracked = null; scrollW_ = width; // assume ScrollSketch not used scrollH_ = height; } // constructor Dragger /** * Called when the mouse is pressed. When called after the mouse is * pressed, the list is searched in reverse order to see if the * cursor is over any of the items. Returns true if any item is * discovered. */ // Dragger boolean checkForDrag() { Clickable tempItem; int i; stillSearching_ = true; itemTracked = null; subItemTracked = null; for (i = draggableList.length - 1; i >= 0; i--) { tempItem = draggableList[i]; if (tempItem.isOver()) { itemTracked = tempItem; subItemTracked = tempItem; return true; } } return false; } // checkForDrag /** * Provides a point that will be tracked during dragging. If the point * specifies the location of an item, using the resulting the object * will move with appropriate coding. Should only be called from * mousePressed(). */ // Dragger void track(int xVal, int yVal) { trackX = xVal; trackY = yVal; startCursorX = mouseX; startCursorY = mouseY; updatedX = trackX; updatedY = trackY; rptX = 0; rptY = 0; rptW = width; rptH = height; dragging = false; } // track; /** * Terminates a drag. */ // Dragger void endDrag() { dragging = false; wasDragging = false; itemTracked = null; subItemTracked = null; } // endDrag /** * Restricts the point being dragged to the area of the panel * even if the cursor moves outside the area. The default: The * whole sketch. */ // Dragger void setDraggedPointBoundaries(ClickablePanel pnl) { rptX = pnl.x; rptY = pnl.y; rptW = pnl.w; rptH = pnl.h; } // 1 parameter setDraggedPointBoundaries /** * Restricts the point being dragged to the speciafied rectangle * even if the cursor moves outside the area. The default: The * whole sketch. */ // Dragger void setDraggedPointBoundaries(int x, int y, int w, int h) { rptX = x; rptY = y; rptW = w; rptH = h; } // 4 parameter setDraggedPointBoundaries /** * Used to specify how far the mouse can be moved outside the area specified * by setDraggedPointBoundaries (in pixels) before the drag is terminated. * Default = 100 pixels. It can even be negative if you don't want the * point to get to close to the boundaries. */ // Dragger void setOutsideLimit(int distance) { outsideLimit = distance; } // setOutsideLimit /** * Specifies the number of pixels the cursor must be moved before a drag * is begun. This is so that if the user just wants to click the item * but moves the mouse very slightly in the process, a drag will not be * initiated. Default = 4 pixels. But if distance = 0, was dragging * is set true so that a mouse click initiates a drag. */ // Dragger void setMinForDrag(int distance) { minForDrag = distance; } // setMinForDrag /** * Returns the horizontal (x) distance the mouse has moved since it was * pressed. The dragged point is constrained to the specified boundary. * Before returning, it calculates the updated location. This can be * used if the sketch needs to track multiple points. Add the delta * distances to the starting location. */ // Dragger int deltaX() { int dX; dX = mouseX - startCursorX; updatedX = constrain(trackX + dX, rptX, rptX + rptW); return updatedX - trackX; } // deltaX /** * Returns the vertical (y) distance the mouse has moved since it was * pressed. The dragged point is constrained to the specified boundary. * Before returning, it calculates the updated location. This can be * used if the sketch needs to track multiple points. Add the delta * distances to the starting location. */ // Dragger int deltaY() { int dY; dY = mouseY - startCursorY; updatedY = constrain(trackY + dY, rptY, rptY + rptH); return updatedY - trackY; } // deltaY /** * Returns the current horizontal (x) coordinate of the tracted point. */ // Dragger int getUpdatedX() { return updatedX; } // updateX /** * Returns the current vertical (y) coordinate of the tracted point. */ // Dragger int getUpdatedY() { return updatedY; } // updateY /** * updateDrag() normally should be called by mouseMoved(). It checks * to see * 1. if the mouse has moved outside the rectangle allowed for the * drag. (See setDraggedPointBoundaries() ). If so, the drag is * terminated. * 2. if the mouse has moved far enough that a drag should be * initiated. (See setMinForDrag.) */ // Dragger void updateDrag() { // make sure something is ready to be dragged if (subItemTracked == null) return; // make sure the mouse is still in the allowed area if (mouseX < subItemTracked.sX(rptX) - outsideLimit || mouseX > subItemTracked.sX(rptX) + rptW + outsideLimit || mouseY < subItemTracked.sY(rptY) - outsideLimit || mouseY > subItemTracked.sY(rptY) + rptH + outsideLimit) { dragging = false; wasDragging = true; itemTracked = null; subItemTracked = null; return; } // has the mouse moved far enough to start a drag? if (abs(mouseX - startCursorX) >= minForDrag || abs(mouseY - startCursorY) >= minForDrag) { dragging = true; wasDragging = true; } // calculate the amounts moved and updated points. if (dragging) { deltaX(); deltaY(); } } // updateDrag /** * Returns the item be tracked. */ // Dragger Clickable getItemTracked() { return itemTracked; } // getTrackedItem /** * Allows setting the subitem that is actually being tracked for compound * items. E.g. itemIracked might be a ScrollSketch while subItemTracked * would be one of its ScrollBars */ // Dragger void setSubItemTracked(Clickable subItem) { subItemTracked = subItem; } // setSubItemTracked /** * Returns "dragging", i.e. is something being dragged. */ // Dragger boolean getDragging() { return dragging; } // getDragging /** * Returns "wasDragging", i.e. was something being dragged before the * drag was terminated by updateDrag(). This can useful to avoid * unwanted clicks after the mouse button is released even if the * mouse is released by updateDrag() or endDrag() even though the * mouse actually still pressed. */ // Dragger boolean getWasDragging() { return wasDragging; } // getWasDragging /** * Returns the list of draggable items. Will be null if the list has * not been provided. */ // Dragger Clickable[] getDraggableList() { return draggableList; } // getDraggableList } // class Dragger // ******************************************************* /** A Draggable is a ClickablePanel with extra features that * simplify dragging. */ abstract class Draggable extends ClickablePanel { boolean processClicks; // Process clicks to scroll bar; /** * Creates a Draggable allowing the most generality. */ Draggable(int leftX, int topY, int theWidth, int theHeight, String theLabel, color stdColor) { super(leftX, topY, theWidth, theHeight, theLabel, stdColor); } // 6 parameter constructor Draggable /** * Construct an invisible ClickablePanel given its location, width, height, * and label (which is not displayed) but without any color. */ Draggable(int leftX, int topY, int theWidth, int theHeight, String theLabel) { super(leftX, topY, theWidth, theHeight, theLabel); // the color is ignored when drawing the panel } // 5 parameter constructor invisible Draggable /** * Makes the entire sketch an invisible ClickablePanel given only a * label (which is not displayed). */ Draggable(String theLabel){ super(0, 0, 0, 0, theLabel, #000000); } // 1 paramerter constructor Draggable /** * This "abstract" method simplifies working with items that can be * dragged. It just returns false and MUST be overridden. It would * be called by the mousePressed() method. */ // Draggable boolean readyForDrag(Dragger theTracker) { return false; } // readyForDrag /** * An "abstract" method that simplifies working with items that can * be dragged. It just returns false and MUST be overridden. This * method would be called by the mouseDragged() method. When implimented, * it will verify the item is the current draggable item and will carry * the actions associated with the drag. */ // Draggable boolean moved(Dragger theTracker) { return false; } //moved /** * Sets processClicks true or false. When processClicks is true, the scroll * button is moved to the location of a click on the bar. False is the * default. (This option does not apply to up and down buttons if they * are present. processClicks must be implemented in the isOver() and * checkForClicks() methods in order for it to work.) */ // Draggable void setProcessClicks(boolean clicks) { processClicks = clicks; } // setProcessClicks } // class Draggable // ******************************************************* /** * DraggablePanel is a simple extension of Clickable Panel * that includes drag capabilities. The panel automatically * drags without any additional coding in the sketch using * the panel other than the standard mousePressed and * mouseDragged coding. */ class DraggablePanel extends Draggable { /** * Constructs a panel which can be dragged. It uses the same parameters * as the first constructors of ClickablePanel and Draggable. */ DraggablePanel(int leftX, int topY, int theWidth, int theHeight, String theLabel, color stdColor) { super(leftX, topY, theWidth, theHeight, theLabel, stdColor); } // 6 parameter DraggablePanel /** * Constructs an invisible panel which can be dragged. It use the * same parameters as the second constructors of ClickablePanel and * Draggable. Because it is invisible, no color is specified. It * particularly useful for making things that are not draggable * appear to be draggable. */ DraggablePanel(int leftX, int topY, int theWidth, int theHeight, String theLabel) { super(leftX, topY, theWidth, theHeight, theLabel); } // 5 parameter DraggablePanel /** * Allows the user sketch to respond to clicks and also implements * the process clicks option. If needed, call from draw() or a * submethod. */ // DragablePanel boolean checkForClick() { if (processClicks && over) { x = mouseX - w/2; y = mouseY - h/2; return true; } else if (over) { return true; } return false; } // checkForClick /** * Determines if the panel has experienced a mousePressed event and * could be ready for a mouse drag. It sets the starting point * position. The minimumForDrag is left as the default and the drag * boundaries to thoses of the panel. It is called by mousedPressed(). * Returns true if the cursor is above the panel and thus the * panel is ready to be dragged. */ // DraggablePanel boolean readyForDrag(Dragger theTracker) { if (over) { theTracker.track(x, y); if (scrollW_ == 0) scrollW_ = width; if (scrollH_ == 0) scrollH_ = height; theTracker.setDraggedPointBoundaries (0, 0, scrollW_, scrollH_); return true; } return false; } // readyForDrag /** * If the panel is the current draggable item, it moves the panel * and returns true. It is called by mouseDragged(). */ // DraggablePanel boolean moved(Dragger theTracker) { if (theTracker.getItemTracked() == this) { theTracker.updateDrag(); x = theTracker.getUpdatedX(); y = theTracker.getUpdatedY(); return true; } return false; } // moved } // class DraggablePanel // ******************************************************* /** * ScrollPane - a two dimensional scroll bar. It has a scroll button * which can be dragged in any direction in a ClickablePanel. The * scroll button is restricted to the panel. The panel values * corresponding to both the horizontal and vertical location. */ class ScrollPane extends Draggable { int scrollBtnX, scrollBtnY; // The upper left hand corner of the // scroll button int scrollBtnW, scrollBtnH; // Width and height of the scroll button float valX, valY; // Values corresponding to the current button location float minValX, maxValX, valRangeX; // Horizontal value limits and range float minValY, maxValY, valRangeY; // Vertical value limits and range color scrollBtnFillColor, scrollBtnBorderColor; // Fill and border colors of the button. Use 0x00FFFFFF for transparent Button scrollBtn; // the ScrollPane's scroll button Clickable scrollBtnDragged; // the button if is currently draggable int scrollW, scrollH; // the amounts that the button can be moved Clickable canBeDragged; Draggable vScroll; /** * Constructor for ScrollPane a two dimensional scroll bar. Includes * a scroll button that can be moved both horizontally and vertically. * To make the ScrollPane almost invisible: Use a transparent color * 0x00000000 (where the first "00" means transparent but starting with * 0xFF would mean 100% opaque). Then display the ScrollPane panel * on top of whatever should be seen. See the DraggerDemo for an * example. * Parameters: * int leftX, int topY: Location of ScrollPane panel * int theWidth, int theHeight: Size of joy stick panel * int btnW, int btnH: Size of scroll button * color stdColor: Color of ScrollPane panel. (Use 0x00000000 for transparent.) * color btnFillColor: Fill color of button. (0x00000000 for transparent.) * color btnBorderColor: Border color of button. * float minValueX: Value corresponding to left side of the panel. * float valueX: Current horizontal value of panel. * float maxValueX: Value corresponding to right side of the panel. * // minValueX > maxValueX is OK * float minValueY: Value corresponding to the bottom of the panel. * float valueY: Current vertical value of panel. * float maxValueY: Value corresponding to top of the panel. * // minValueY > maxValueY is OK */ ScrollPane(int leftX, int topY, int theWidth, int theHeight, int btnW, int btnH, color stdColor, color btnFillColor, color btnBorderColor, float minValueX, float valueX, float maxValueX, float minValueY, float valueY, float maxValueY) { super(leftX, topY, theWidth, theHeight, "ScrollPane", stdColor); scrollBtnFillColor = btnFillColor; scrollBtnBorderColor = btnBorderColor; minValX = minValueX; valX = valueX; maxValX = maxValueX; valRangeX = maxValueX - minValueX; // can be negative minValY = minValueY; valY = valueY; maxValY = maxValueY; valRangeY = maxValueY - minValueY; // can be negative scrollBtnX = calcLocX(valueX); scrollBtnY = calcLocY(valueY); scrollBtnW = btnW; scrollBtnH = btnH; scrollBtn = new Button(scrollBtnX, scrollBtnY, scrollBtnW, scrollBtnH, "", btnFillColor, btnFillColor); scrollBtn.setBorderColor(btnBorderColor); scrollW = w - scrollBtnW; scrollH = h - scrollBtnH; } // constructor ScrollPane /** * Sets the ScrollPane as being visible true or false. The panel * is non functional when visible is false. */ // ScrollPane void setVisible(boolean b) { scrollBtn.setVisible(b); visible = b; } // setVisible /** * Sets the ScrollPane as being enabled true or false. */ // ScrollPane void setEnabled(boolean b) { scrollBtn.setEnabled(b); enabled = b; } // setVisible /** * Displays the ScrollPane panel and button. */ // ScrollPane void display() { super.display(); scrollBtn.display(); } // display /** * Determines if the cursor is over any part of the ScrollPane * and returns true if so. Always returns false if stillSearching_ * is false or if it is invisible or disabled. */ // ScrollPane boolean isOver() { if (!visible || !enabled) return false; over = false; if (scrollBtn.isOver()) { // must check button first because of stillSearching_ over = true; } else if (processClicks && super.isOver()){ over = true; } if (over) stillSearching_ = false; return over; } // isOver /** * Checks to see if any part of the "ScrollPane" has been * clicked. If so, it updates the current "value" and sets "clicked" * to true and then returns true. Uses the click as the center of * the buttom subject limits on the button. isOver() must be called * before checkForClick(). */ // ScrollPane boolean checkForClick() { boolean b; int tempX, tempY; if (!visible || !enabled) return false; b = false; if (scrollBtn.over) { // must check scrollBtn first b = true; } else if (processClicks && over) { b = true; } if (b) { tempX = mouseX + soX_ - scrollBtnW/2; /// ???????????? tempY = mouseY + soY_ - scrollBtnH/2; /// ???????????? setScrollBtnPos(tempX, tempY); // move button and recalculate } return b; } // checkForClick /** * Determine if the ScrollPane has been clicked. If so, return true * after "clicked" is set to false. */ // ScrollPane boolean hasBeenClicked() { boolean b; if (!visible || !enabled) return false; b = false; if (scrollBtn.hasBeenClicked()) { b = true; } else if (clicked) { b = true; } clicked = false; return b; } // hasBeenClicked /** * If the pane is the current draggable item, it moves the scroll * Button and returns true. Ignores clicks on the panel outside * of the button. It is called by mousePressed(). */ // ScrollPane boolean readyForDrag(Dragger theTracker) { canBeDragged = null; if (scrollBtn.over) { canBeDragged = scrollBtn; theTracker.track(scrollBtn.x, scrollBtn.y); theTracker.setDraggedPointBoundaries(this); theTracker.setSubItemTracked(scrollBtn); scrollBtnDragged = scrollBtn; return true; } return false; } // readyForDrag /** * If the ScrollPane is the current draggable item, it moves the scroll * button and returns true. It is called by mouseDragged(). */ // ScrollPane boolean moved(Dragger theTracker) { if (scrollBtnDragged == scrollBtn) { setScrollBtnPos(theTracker.getUpdatedX(), theTracker.getUpdatedY()); return true; /////???????????????????? } return false; } /** * Returns the x location (left side) of button */ // ScrollPane int getButtonX() { return scrollBtn.x; } // getButtonX /** * Returns the y location (top) of button */ // ScrollPane int getButtonY() { return scrollBtn.y; } // getButtonY /** * Calculates and returns the location that corresponding to the x value * The value is restricted to legal x values as specified by the minValX * maxValX. Does not change values or locations. */ // ScrollPane int calcLocX(float value) { value = constrain(value, min(minValX, maxValX), max(minValX, maxValX)); return x + (int)((w - scrollBtnW) * (value - minValX)/valRangeX); } // calcLocX /** * Sets value corresponding to x and the location that corresponds to it. * The value is stricted to legal x values as specified by the minValX * maxValX. */ // ScrollPane void setValueX(float value) { valX = constrain(value, min(minValX, maxValX), max(minValX, maxValX)); scrollBtnX = calcLocX(valX); setScrollBtnPos(scrollBtnX, scrollBtnY); } // setValueX /** * Calculates and returns the location that corresponding to the y value * The value is restricted to legal y values as specified by the minValY * maxValY. */ // ScrollPane int calcLocY(float value) { value = constrain(value, min(minValY, maxValY), max(minValY, maxValY)); return y + (int)((h - scrollBtnH) * (value - minValY)/valRangeY); } // calcLocY /** * Sets value corresponding to y and the location that corresponds to it. * The value is stricted to legal y values as specified by the minValY * maxValY. */ // ScrollPane void setValueY(float value) { valY = constrain(value, min(minValY, maxValY), max(minValY, maxValY)); scrollBtnY = calcLocY(valY); setScrollBtnPos(scrollBtnX, scrollBtnY); } // setValueY /** * Set the absolute position (x, y) of the Button constained * by the limits on the x and y values. */ // ScrollPane void setScrollBtnPos(int xLoc, int yLoc) { scrollBtnX = constrain(xLoc, x, x + scrollW); scrollBtnY = constrain(yLoc, y, y + scrollH); scrollBtn.x = scrollBtnX; scrollBtn.y = scrollBtnY; calcValues(); } // setScrollBtnPos /** * Calculates and stores valX and valY (the X and Y values) * based on the location of scrollBtn. */ // ScrollPane void calcValues() { valX = minValX + valRangeX * (float)(scrollBtnX - x)/scrollW; valY = minValY + valRangeY * (float)(scrollBtnY - y)/scrollH; } // calcVal /** * Returns the current X value of the ScrollPane. */ // ScrollPane float getValueX() { return valX; } // getValueX /** * Returns the max X value of the ScrollPane. */ // ScrollPane float getMaxValueX() { return maxValX; } // getMaxValueX /** * Returns the min X value of the ScrollPane. */ // ScrollPane float getMinValueX() { return minValX; } // getMinValueX /** * Returns the current Y value of the ScrollPane. */ // ScrollPane float getValueY() { return valY; } // getValueY /** * Returns the max Y value of the ScrollPane. */ // ScrollPane float getMaxValueY() { return maxValY; } // getMaxValueY /** * Returns the in Y value of the ScrollPane. */ // ScrollPane float getMinValueY() { return minValY; } // getMinValueY /** * Set width of scrollBtn and recalculate. */ // ScrollPane void setScrollBtnWidth(int theWidth) { scrollBtnW = theWidth; scrollW = w - scrollBtnW; setValueX(getValueX()); scrollBtn.w = scrollBtnW; } // setScrollBtnWidth /** * Set height of scrollBtn and recalculate. */ // ScrollPane void setScrollBtnHeight(int theHeight) { scrollBtnH = theHeight; scrollH = h - scrollBtnH; setValueY(getValueY()); scrollBtn.h = scrollBtnH; } // setScrollBtnWidth } // class ScrollPane // ******************************************************* /** * The ScrollBar class creates a standard looking scrollbar with many options. The bar can be * either vertical or horizontal. It is includes a draggable scroll button and up/right and down/left * buttons. There are two constructors. See the ScrollerDemo * description for the options. */ class ScrollBar extends Scroller { /** * Most general onstructor for ScrollBar. Its orientation * can be either vertical or horizontal. It includes buttons at * either end that move the scroll button by about 10% of the * length of the scroll bar. * Parameters: * boolean vert: Orientation: true - vertical, false - horizontal * int leftX, int topY: Location of ScrollBar panel * int theWidth, int theHeight: Size of scrollbar panel * int btnSize: Size (height/width) of scroll button * String theLabel: Label for ScrollBar (not shown) * color stdColor: Color of ScrollBar panel. * color btnFillColor: Fill color of button. * float minValue: Value corresponding to the bottom/left end of the panel. * float maxValue: Value corresponding to the top/right end of the panel. * // minValue > maxValue is OK */ ScrollBar(boolean vert, int leftX, int topY, int theWidth, int theHeight, int btnSize, String theLabel, color stdColor, color btnFillColor, float minValue, float maxValue) { super(vert, leftX, topY, theWidth, theHeight, theLabel, stdColor, btnFillColor, minValue, maxValue); if (vertical) { scrollBtn = new Button(x, scrollBtnPos, w, BUTTON_SIZE, "", btnFillColor, btnFillColor); upBtn = new Button(x, y, w, BUTTON_SIZE, " ^", btnFillColor, btnFillColor); downBtn = new Button(x, y + h - BUTTON_SIZE, w, BUTTON_SIZE, " v", btnFillColor, btnFillColor); } else { scrollBtn = new Button(scrollBtnPos, y, BUTTON_SIZE, h, "", btnFillColor, btnFillColor); upBtn = new Button(x, y, BUTTON_SIZE, h, " <", btnFillColor, btnFillColor); downBtn = new Button(x + w - BUTTON_SIZE, y, BUTTON_SIZE, h, " >", btnFillColor, btnFillColor); } setScrollValues(); setValue(smallerVal); } // most general constructor ScrollBar /** * Simplified constructor for HScrollBar. Includes a scroll * button that can be moved both horizontally and left and * right buttons. * Parameters: * int leftX, int topY: Location of HScrollBar panel * int theSize: Size (height/width) of scrollbar panel * float minValue: Value corresponding to the bottom/left end of the panel. * float maxValue: Value corresponding to the top/right end of the panel. * // minValue > maxValue is OK */ ScrollBar(boolean vert, int leftX, int topY, int theSize, float minValue, float maxValue) { this (vert, leftX, topY, select_(vert, BUTTON_SIZE, theSize), select_(vert, theSize, BUTTON_SIZE), BUTTON_SIZE, "Scroll bar", #E0E0E0, #C0C0C0, minValue, maxValue); } // simplified constructor ScrollBar } // ScrollBar // ******************************************************* /** * Same as ScrollBar but lacks the up/down buttons */ class SimpleScrollBar extends Scroller { /** * */ SimpleScrollBar(boolean vert, int leftX, int topY, int theSize, float minValue, float maxValue) { super (vert, leftX, topY, select_(vert, BUTTON_SIZE, theSize), select_(vert, theSize, BUTTON_SIZE), "SimpleScrollBar", #E0E0E0, #C0C0C0, minValue, maxValue); if (vertical) { scrollBtn = new Button(x, scrollBtnPos, BUTTON_SIZE, BUTTON_SIZE, "", #C0C0C0, #A0A0A0); } else { scrollBtn = new Button(scrollBtnPos, y, BUTTON_SIZE, BUTTON_SIZE, "", #C0C0C0, #A0A0A0); } setSizes(BUTTON_SIZE); setScrollValues(); setValue(smallerVal); } // constructor SimpleScrollBar } // class SimpleScrollBar // ******************************************************* /** * Same as ScrollBar but lacks the up/down buttons */ class Slider extends Scroller { static final int SLIDER_SIZE = 5; /** * Creats a slider - bar with a circular scroll button. */ Slider(boolean vert, int leftX, int topY, int theSize, float minValue, float maxValue) { super (vert, leftX, topY, select_(vert, SLIDER_SIZE, theSize), select_(vert, theSize, SLIDER_SIZE), "Slider", #E0E0E0, #C0C0C0, minValue, maxValue); if (vertical) { scrollBtn = new CircleButton(x + 3, scrollBtnPos, 5 * SLIDER_SIZE/4, "", #C0C0C0, #A0A0A0); } else { scrollBtn = new CircleButton(scrollBtnPos, y + 3, 5 * SLIDER_SIZE/4, "", #C0C0C0, #A0A0A0); } setScrollValues(); adjustForCircleScrollBtn(); setValue(smallerVal); } // constructor Slider } // class Slider // ******************************************************* /** * Scroller - an abstract scroll bar that can be extended by other * classes in several ways. It has a scroll button which can be * dragged in the bar. The orientation depends on whether * height > width. */ abstract class Scroller extends Draggable { static final int BUTTON_SIZE = 20; // Height/width of up & down buttons. int scrollBtnPos; // The y value of upper end of the scroll button or // x value of left end of the scroll button depending // on the orientation of the scroll button. int scrollBtnSize; // The height or width of the scroll button. int upDownBtnSize; // The height/width of the up/down buttons. 0 if not used. int scrollLength; // The distance the scroll button can moved. int scrollMin; // The upper most or left most position of scroll button. float val; // Value corresponding to the current scroll button location. float minVal, maxVal, valRange; // Value limits and range. float smallerVal; // Minimum of mimVal and maxVal. (maxVal < minVal is OK). float biggerVal; // Maximum of mimVal and maxVal (maxVal < minVal is OK). color scrollBtnFillColor, scrollBtnBorderColor; // Fill and border colors of button. Use 0x00000000 for transparent. Button scrollBtn; // The ScrollBar's scroll button. Button upBtn, downBtn; // The down/left and up/right buttons. Clickable canBeDragged; // The button if is currently draggable. boolean vertical; // Orientation of the bar. float hashStart, hashSpacing; // First value and increment for hash markings. boolean hashShow; // Show hashmarks if true. float labelsStart, labelsSpacing; // First value and increment for labels. boolean labelsShow; // Show labels if true. boolean valueShow; // Show current value if true. int upDownDivisor; // Mvement divisor for up/down buttons. int circleAdjust; // Adjustment need in location for circular scroll btn. // Required because circles use center loctions instead // of edge locations. /** * Constructor for Scroller. The scroll button must be added by the * class that extends the Scroller allowing a variety of implimentations. * Likewise The up/down or left/right buttons can optionally added by * the extending classes. In addition, one can reset the following as * appropriate: * scrollMin: The minimal value of scrollBtnPos. * scrollLength: The distance the scroll button can travel. For * vertical bars, scrollLength - combined height of * the buttons. * scrollBtnPos = calcLoc(desired initial value of scrollBar); * scrollBtnSize = setSizes(desired scroll button height or width); * * Parameters: * boolean verticalOrientation: true for vertical, false for horizontal * int leftX, int topY: Location of ScrollBar panel. * int theWidth, int theHeight: Size of scrollbar panel. * String theLabel: Label for ScrollBar (not shown) * color stdColor: Color of ScrollBar panel. * color btnFillColor: Fill color of button. * float minValue: Value corresponding to left side of the panel. * float maxValue: Value corresponding to right side of the panel. * // minValueX > maxValueX is OK */ Scroller(boolean verticalOrientation, int leftX, int topY, int theWidth, int theHeight, String theLabel, color stdColor, color btnFillColor, float minValue, float maxValue) { super(leftX, topY, theWidth, theHeight, theLabel, stdColor); vertical = verticalOrientation; scrollBtnFillColor = btnFillColor; minVal = minValue; val = minValue; maxVal = maxValue; calcMinMaxRelatedValues(); scrollBtnSize = 0; upDownBtnSize = 0; // assume no updown buttons // default values - normally they need to be overriden! upBtn = null; downBtn = null; if (vertical) { if (minVal <= maxVal) { scrollMin = topY + h; scrollLength = -h; } else { scrollMin = topY; scrollLength = h; } } else { if (minVal <= maxVal) { scrollMin = leftX; scrollLength = w; } else { scrollMin = leftX + w; scrollLength = -h; } } circleAdjust = 0; processClicks = false; // scrollBtnPos must be recalculated after scrollMin and scrollLength // are specified. scrollBtnPos = calcLoc(minValue); } // constructor scroller /** * Calculates valRange, smallerVal, and biggerVal. That is, the * values related to the max and min values. */ // Scroller void calcMinMaxRelatedValues() { smallerVal = min(minVal, maxVal); biggerVal = max(minVal, maxVal); valRange = biggerVal - smallerVal; // always positive if (vertical) upDownDivisor = -10; // movement for up button else upDownDivisor = 10; // movement for right button val = constrain(val, smallerVal, biggerVal); } // calcMinMaxRelatedValues /** * Set scroll values. They include the button size and * whether the bar has up/right and down/left buttons. Values are * determined by the scrollbutton and the upBtn (if it exists). */ // Scroller void setScrollValues() { if (vertical) { // scroll button position a top of button scrollBtnSize = scrollBtn.getH(); if (upBtn != null) { // assumes downBtn exists and has same size upDownBtnSize = upBtn.getH(); } else { upDownBtnSize = 0; } } else { // scroll button position at left end of button scrollBtnSize = scrollBtn.getW(); if (upBtn != null) { // assumes downBtn exists and has same size upDownBtnSize = upBtn.getW(); } else { upDownBtnSize = 0; } } setSizes(scrollBtnSize); scrollBtnPos = calcLoc(smallerVal); } // setScrollValues /** * Set size (height/width) of scrollBtn and calculate * scrollMin and ScrollLength. Must be called by * extending classes after creating any and all buttons * in order to complete the construction. Can be called * by the user sketch to reset the scroll button size. * "theSize" is the height or width (depending on the * orientation) of the scroll button and can be as small * as -1 in which case the button is just a line and * cannot be dragged. */ // Scroller void setSizes(int theSize) { float saveValue; saveValue = getValue(); scrollBtnSize = max(-1, theSize); // size -1 hard to detect but prevents scrolling if (vertical) { scrollLength = h - 2 * upDownBtnSize - scrollBtnSize; scrollBtn.h = scrollBtnSize; if (minVal <= maxVal){ scrollMin = y + h - scrollBtnSize - upDownBtnSize; scrollLength = -scrollLength; } else { scrollMin = y + upDownBtnSize; } } else { // horizontal scrollLength = w - 2 * upDownBtnSize - scrollBtnSize; scrollBtn.w = scrollBtnSize; if (minVal <= maxVal) { scrollMin = x + upDownBtnSize; } else { scrollMin = x + w - scrollBtnSize - upDownBtnSize; scrollLength = -scrollLength; } } setValue(saveValue); scrollBtnPos = calcLoc(smallerVal); } // setSizes /** * Sets a value(half of w) to add to location of a circular scroll button * to correct for its shape. This is needed because the x or y represents * the center of the circle instead of the left or top of the figure as * it does for regular buttons. */ // Scroller void adjustForCircleScrollBtn() { float temp; temp = val; circleAdjust = scrollBtn.w/2; setScrollBtnPos(calcLoc((int)temp)); } // adjustForCircleScrollBtn /** * Sets the Scroller as being visible true or false. The panel * is non functional when visible is false. */ // Scroller void setVisible(boolean b) { scrollBtn.setVisible(b); visible = b; } // setVisible /** * Sets the Scroller as being enabled true or false. */ // Scroller void setEnabled(boolean b) { scrollBtn.setEnabled(b); enabled = b; } // setVisible /** * Sets the scroller and all its parts to scroll or not scroll * when the whole sketch scrolls. */ // Scroller void setScrollable(boolean canScroll) { if (upBtn != null); upBtn.setScrollable(canScroll); if (downBtn != null); downBtn.setScrollable(canScroll); scrollBtn.setScrollable(canScroll); scrollable = canScroll; } // setScrollable /** * Displays the Scroller panel and its button(s). */ // Scroller void display() { super.display(); if (hashShow) displayHashMarks(); if (labelsShow) displayLabels(); if (valueShow) displayValue(); scrollBtn.display(); if (upBtn != null) upBtn.display(); if (downBtn != null) downBtn.display(); if (hashShow || labelsShow) displayBtnLine(); } // display /** * Determines if the cursor is over any part of the Scroller * and sets the over field to true and returns true if so. * Always returns false if stillSearching_ */ // Scroller boolean isOver() { if (!visible || !enabled) return false; over = false; if (!stillSearching_) return false; if (scrollBtn.isOver()) { // must check button first because of stillSearching_ over = true; } else if ((upBtn != null && upBtn.isOver()) || (downBtn != null && downBtn.isOver())) { over = true; } else if (processClicks && super.isOver()) { over = true; } if (over) stillSearching_ = false; return over; } // isOver /** * Checks to see if any part of the scroller has been clicked. If so, * it updates the current "value" as needed and sets "clicked" to true * and then returns true. Processes the up and down buttons if they are * not null. setScrollBtnPos checks to make sure the position is legal. * It is called by mouseReleased(). */ // Scroller boolean checkForClick() { boolean b; int temp; if (!visible || !enabled) { return false; } b = false; if (scrollBtn.over) { // must check scrollBtn first if (vertical) { temp = mouseY - scrollBtn.h/2; } else temp = mouseX - scrollBtn.w/2; setScrollBtnPos(temp); // move button and recalculate b = true; } else if (upBtn != null && upBtn.over) { setScrollBtnPos(scrollBtnPos - abs(scrollLength/upDownDivisor)); b = true; } else if (downBtn != null && downBtn.over) { setScrollBtnPos(scrollBtnPos + abs(scrollLength/upDownDivisor)); b = true; } else if (over && processClicks) { if (vertical) temp = mouseY - scrollBtn.h/2; else temp = mouseX - scrollBtn.w/2; setScrollBtnPos(temp); // move button and recalculate b = true; } return b; } // checkForClick /** * Determines if the Scroller has been clicked. If so, return true * after "clicked" is set to false. It is called by draw() or a * submethod. */ // Scroller boolean hasBeenClicked() { boolean b; if (!visible || !enabled) return false; b = false; if (scrollBtn.hasBeenClicked()) { b = true; } else if ((upBtn != null && upBtn.hasBeenClicked()) || (downBtn != null && downBtn.hasBeenClicked())) { b = true; } else if (clicked) { b = true; } clicked = false; return b; } // hasBeenClicked /** * Determines if the Scroller button has experienced a * mousePressed event and could be dragged. Ignores clicks on the * bar outside of the scroll button. Sets the position of the * scrollbutton and then sets the minimumForDrag to 0 and the drag * boundaries to thoses of the scroller. It is called by mousedPressed(). */ // Scroller boolean readyForDrag(Dragger theTracker) { canBeDragged = null; if (scrollBtn.over) { canBeDragged = scrollBtn; if (vertical) theTracker.track(0, getButtonPos()); else theTracker.track(getButtonPos(), 0); theTracker.setMinForDrag(0); theTracker.setDraggedPointBoundaries(this); return true; } return false; } // readyForDrag /** * If the scrollbutton is the current draggable item, it moves the button * and returns true. It is called by mouseDragged(). */ // Scroller boolean moved(Dragger theTracker) { if (theTracker.getItemTracked() != this) { return false; } if (canBeDragged == scrollBtn) { if (vertical) setScrollBtnPos(theTracker.getUpdatedY()); else setScrollBtnPos(theTracker.getUpdatedX()); calcValue(); return true; } return false; } //moved /** * Calculates and returns the location that corresponds to the position * of scrollbutton. The value is stricted to legal values as specified * by the minVal and maxVal. Does not change values or locations. */ // Scroller int calcLoc(float value) { int tempLoc; value = constrain(value, smallerVal, biggerVal); if (valRange == 0) tempLoc = scrollMin + scrollLength/2; else tempLoc = scrollMin + (int)(scrollLength * (value - smallerVal)/valRange); return tempLoc; } // calcLoc /** * Calculates and stores val (the value) using location of scrollBtn. */ // Scroller void calcValue() { if (scrollLength != 0) val = smallerVal + valRange * (float)(scrollBtnPos - scrollMin) /scrollLength; } // calcVal /** * Returns the current value of the Scroller. */ // Scroller float getValue() { return val; } // getValue /** * Returns the max (top or right) value of the Scroller. */ // Scroller float getMaxValue() { return maxVal; } // getMaxValue /** * Returns the min (bottom or left) value of the Scroller. */ // Scroller float getMinValue() { return minVal; } // getMinValue /** * Returns the location (top or left end) of button */ // Scroller int getButtonPos() { if (vertical) return scrollBtn.y; else return scrollBtn.x; } // getButtonPos /** * Called by display() when showHashmarks is true. It displays hashmarks * on the right side or bottom of the Scroller. */ // Scroller void displayHashMarks() { float theValue; int offset; int yLoc, xLoc; stroke(0); offset = scrollBtnSize/2; if (vertical) { xLoc = sX(x + w); for (theValue = hashStart; theValue <= biggerVal; theValue += hashSpacing) { yLoc = sY(calcLoc(theValue) + offset);; line(xLoc, yLoc, xLoc + 6, yLoc); } } else { yLoc = sY(y + h); // Calculate sY(y + h) once for (theValue = hashStart; theValue <= biggerVal; theValue += hashSpacing) { xLoc = sX(calcLoc(theValue) + offset); line(xLoc, yLoc, xLoc, yLoc + 6); } } } // displayHashMarks /** * Called by display() when showLabels is true. It displays labels on the * right side or bottom of the Scroller. */ // Scroller void displayLabels() { float theValue; int offset; int yLoc, xLoc; stroke(0); fill(0); offset = scrollBtnSize/2; if (vertical) { xLoc = sX(x + w); for (theValue = labelsStart; theValue <= biggerVal; theValue += labelsSpacing) { if (theValue >= smallerVal) { yLoc = sY(calcLoc(theValue) + offset); line(xLoc, yLoc, xLoc + 6, yLoc); text("" + round2_(theValue), xLoc + 8, yLoc + 3); } } } else { yLoc = sY(y + h); for (theValue = labelsStart; theValue <= biggerVal; theValue += labelsSpacing) { xLoc = sX(calcLoc(theValue) + offset); line(xLoc, yLoc, xLoc, yLoc + 6); text("" + round2_(theValue), xLoc - 7, yLoc + 17); } } } /** * Called by display() when showValue is true. It displays the current value * of the scrollbar. The value is written on the left or top of the bar if * showLabels has been selected. Otherwise it is on the right or * bottom of the bar. */ // Scroller void displayValue() { if (labelsShow) displayOneLabel(val, false); else displayOneLabel(val, true); } // displayValue /** * Draws on marker line in middle of the scroll button to help it show * the value more clearly when called by display(). */ // Scroller void displayBtnLine() { int xLoc, yLoc; if (vertical) { yLoc = sY(scrollBtnPos + scrollBtnSize/2); line(sX(x + w/2), yLoc, sX(x + w), yLoc); } else { xLoc = sX(scrollBtnPos + scrollBtnSize/2); line(xLoc, sY(y + h/2), xLoc, sY(y + h)); } } /** * Makes sure that loc is in the right range, assigns the value to scroll * button as appropriate, and recalculates the value. */ // Scroller void setScrollBtnPos(int loc) { scrollBtnPos = constrain(loc, min(scrollMin, scrollMin + scrollLength), max(scrollMin, scrollMin + scrollLength)); if (vertical) { scrollBtn.y = scrollBtnPos + circleAdjust; } else { scrollBtn.x = scrollBtnPos + circleAdjust; } calcValue(); } // setScrollBtnPos //****************************************************** // Customizing feature for scrollbars and sliders. // Called from draw (or a submethod). //****************************************************** /** * Write a label with the given value beside the scroll bar. * If rightSide is true, then it is on the right side, if not * it is on the left side. The value is rounded to two * decimal places (but may appear 0 or 1 decimal places). * Called from draw() or submethod. */ // Scroller void displayOneLabel(float value, boolean rightSide) { int labelY, labelX; float labelVal; int xLoc, yLoc; stroke(0); fill(0); if (vertical) { yLoc = sY(calcLoc(value) + scrollBtnSize/2); xLoc = sX(x); labelVal = round2_(value); // Note: "" + labelVal is printed because without // the "" +, 3 decimal places are normally shown. if (rightSide) { text("" + labelVal, xLoc + w + 8, yLoc + 3); line(xLoc + w, yLoc, xLoc + w + 5, yLoc); } else { // left side text(labelVal + "", xLoc - 40, yLoc + 3); line(xLoc - 5, yLoc, xLoc, yLoc); } } else { xLoc = sX(calcLoc(value) + scrollBtnSize/2); yLoc = sY(y); labelVal = round2_(value); if (rightSide) { //bottom text("" + labelVal, xLoc - 5, yLoc + h + 17); line(xLoc, yLoc + h, xLoc, yLoc + h + 5); } else { // top text("" + labelVal, xLoc - 5, yLoc - 7); line(xLoc, yLoc - 5, xLoc, yLoc); } } } // displayOneLabel //****************************************************** // Customizing feature for scrollbars and sliders. // Normally called from setup. //****************************************************** /** * Set the colors (standard and "over") of the button. */ //Scroller void setButtonFillColors(color fillColor, color overFillColor) { scrollBtnFillColor = fillColor; scrollBtn.c[0] = fillColor; scrollBtn.overC[0] = overFillColor; } // setButtonFillColors /** * Sets the scrollBtn's border color */ // Scroller void setButtonBorderColor(color borderColor) { scrollBtn.setBorderColor(borderColor); } // setButtonBorderColor /** * Set the colors of the scroll bar. */ // Scroller void setBarColors(color stdColor, color overStdColor) { c[0] = stdColor; overC[0] = overStdColor; } // setBarColor /** * Sets value corresponding to the location of the scrollButton and * the location that corresponds to it. The value is stricted to legal * values as specified by the minVal and maxVal. */ // Scroller void setValue(float value) { val = constrain(value, smallerVal, biggerVal); if (valRange == 0) scrollBtnPos = scrollMin + scrollLength/2; else scrollBtnPos = scrollMin + (int)(scrollLength * (value - smallerVal)/valRange); if (vertical) scrollBtn.y = scrollBtnPos + circleAdjust; else scrollBtn.x = scrollBtnPos + circleAdjust; } // setValue /* * Set the minimum value of the scroller and adjusts the scrollbutton. * This value is used at the top or right end of the scroll bar. * (Recall minValue > maxValue is legal.) After setting a new * min and/or max value, use calcMinMaxRelatedValues() to set some * internal values. */ // Scroller void setMinValue(float minValue) { // float saveVal; // saveVal = val; minVal = minValue; calcMinMaxRelatedValues(); setValue(val); } // setMinValue /* * Set the max value of the scroller and adjusts the scrollbutton. * This value is used at the top or right end of the scroll bar. * (Recall minValue > maxValue is legal.) After setting a new * min and/or max value, use calcMinMaxRelatedValues() to set some * internal values. */ // Scroller void setMaxValue(float maxValue) { // float saveVal; // saveVal = val; maxVal = maxValue; calcMinMaxRelatedValues(); setValue(val); } // setMaxValue /** * Adds labels showing the value to the left or bottom of the * meter. First label is at start. Note: This version * is designed for situations where the <> minimal value is * a nice number. Should be called in setup. */ // Scroller void showLabels(float spacing, float start) { labelsStart = start; labelsSpacing = spacing; labelsShow = true; } // 2 parameter showLabels /** * Adds labels showing the value to the left or bottom of the * meter. First label is at minValue. Note: This version * is designed for situations where the minimal value is * a nice number. Should be called in setup. */ // Scroller void showLabels(float spacing) { labelsStart = smallerVal; labelsSpacing = spacing; labelsShow = true; } // 1 parameter showLabels /** * Adds hashmarks to the left or bottom of the meter. * First hash is at start. Note: This version * is designed for situations where the minimal value is * <> a nice number. Should be called in setup. */ // Scroller void showHashmarks(float spacing, float start) { hashStart = start; hashSpacing = spacing; hashShow = true; } // 2 parameter showHashMarks /** * Adds hashmarks to the left or bottom of the meter. * First hash is at minValue. Note: This version * is designed for situations where the minimal value is * a nice number. Should be called in setup. */ // Scroller void showHashmarks(float spacing) { hashStart = smallerVal; hashSpacing = spacing; hashShow = true; } // 1 parameter showHashMarks /** * Adds the value of the meter at the appropriate location. * If showLabels is also used, the labels will appear on * the left or top of the bar. This prevents the value * label from overlapping the other labels. If the show * labels is not used, the labels will appear on the right * or bottom of the bar. */ // Scroller void showValue() { valueShow = true; } // showValue } // class Scroller // ******************************************************* /** * Adds a vertical and horizontal scrollbars to the right and * bottom of the ketch.The user can use these bars to scroll the * sketch. * * All the Clickable items have been adapted to scroll so normally * no extra coding is needed to allow them to scroll. However, * standard Processing items like text, lines and rectangles need * a little extra coding. All the x and y coordianates must be * addapted to use the the global sX_ and sY_ methods found in the * Cickable.pde file. For example, replace * text("Some text", 20, 40); * with * text("Some text", sX_(20), sY_(40)); * If you don't want a Clickable item to scroll, have it call its * setScrollable method. For example, * myButton.setScrollable(false); * For non-Clickable items like text, lines and rectangles, just don't * use the sX_ and sY_ methods. * The ScrollSketch item must be set up carefully. It should be * the last item in the Clickable and it must be created in setup() * after the size of the sketch is specified. For example, * ... * ScrollSketch sWindow = new ScrollSketch(...); * Clickable[] clickItems = {... other Clickable items ..., sWindow}; * ClickableGroup clickGrp = new ClickableGroup(clickItems); * Clickable[] dragItems = {.. other draggaable items ..., sWindow}; * Dragger dragGrp = new Dragger(dragItems); * * void setup() { * size(450, 500); * sWindow.setupScrollSketch(); * ... * * In addition, in draw(), the scrollSketch should be the last thing * drawn. Normally the ClickableGroup should be the last thing * drawn. * * The Clickable.pde file contains global fields soX_ and soY_ which * contain the current scrolling offsets. The global methods sX_() and * sY_() are intended for the user's program. Every clickable item * has the methods sX() and sY() methods that carry out similar operations excepts if the item has been marked as not * for Clickable items except these methods do not adjust the * coordiates if the scrollable field has been set false. */ class ScrollSketch extends Draggable { final int BAR_SIZE = 20; int localScrollW, localScrollH; // Max size of scrolled window // Remember these values int winPaneWidth, winPaneHeight; // Size of displaned pane less bars ScrollBar hScroll; // The horizontal ScrollBar ScrollBar vScroll; // The vertical ScrollBar Clickable canBeDragged; // The button if is currently draggable. color btnColor; // Color of the scroll button. /** * Sets up scrolling for the sketch window. Vertical and horizontal scroll * bars are used. The colors are the standard color, the * color used when cursor is over the scrollbar and the color * used for the bar in scrollbar. * * maxWidth and maxHeight are the maximum size of the scrolled * sketch of which only a portion is shown. * * Note: In Processing, width and height are undefined until * setup is run. Hence the SchollSketch' scroll brs, can't be * created until after the size is set. To complete the construction * setupScrollSketch must be called in setup() immediately after the * size has been set. */ ScrollSketch(int maxWidth, int maxHeight, color theColor, color theOverColor, color buttonColor) { super(0, 0, 0, 0, "ScrollSketch", 0x00000000); scrollW_ = maxWidth; scrollH_ = maxHeight; soX_ = 0; soY_ = 0; c[0] = theColor; overC[0] = theOverColor; btnColor = buttonColor; } // 5 parameter constructor ScrollSketch /** * Sets up scrolling for the sketch window. Vertical and horizontal scroll * bars are used. The colors are the standard color, the * color used when cursor is over the scrollbar and the color * used for the bar in scrollbar. * * The width and height of the scrolled window is about twice * the size of the displayed window. * * Note: In Processing, width and height are undefined until * setup is run. Hence this SchollWindow, can't be created * until after the size is set. Then the new ScroolWindow * must be put in the clickable array and then the * ClicableGroup can be created. */ ScrollSketch(color theColor, color theOverColor, color buttonColor) { this(0, 0, theColor, theOverColor, buttonColor); } // 3 parameter constructor ScrollSketch /** * Sets up scrolling for the sketch window. Vertical and horizontal * scroll bars are used. Uses default colors for the bars and buttons. */ ScrollSketch() { this(0, 0, #EEEEEE, #EEEEEE, #CCCCCC); } // 0 parameter constructor ScrollSketch /** * Completes the construction of a ScrollSketch by creating the * scrollbars and seting some values. Unfortunately the width and * height of the sketch are not known until they have been set at * the beginning of the setup() method hence the final size can be * determined until the size has been set. Use in the * setup() method immediately after size(...,...). In addition, * it adjusts the size of the vertical scrollbar if a menu is * used. */ // ScrollSketch void setupScrollSketch(boolean hasMenu) { int topVScroll; // start by setting the panel rectangle to the full sketch size. w = width; h = height; if (hasMenu) { topVScroll = BAR_SIZE; } else { topVScroll = 0; } winPaneWidth = w - BAR_SIZE ; winPaneHeight = h - BAR_SIZE - topVScroll; if (scrollW_ == 0) scrollW_ = 2 * w; if (scrollH_ == 0) scrollH_ = 2 * h; localScrollW = scrollW_; localScrollH = scrollH_; hScroll = new ScrollBar(false, 0, h - BAR_SIZE, winPaneWidth, BAR_SIZE, BAR_SIZE,"WinHoriScroll", c[0], btnColor, 0, scrollW_ - winPaneWidth); vScroll = new ScrollBar(true, winPaneWidth, topVScroll, BAR_SIZE, winPaneHeight, BAR_SIZE,"WinVertScroll", c[0], btnColor, scrollH_ - winPaneHeight, 0); hScroll.setScrollable(false); vScroll.setScrollable(false); vScroll.setBarColors(c[0], overC[0]); hScroll.setBarColors(c[0], overC[0]); vScroll.setButtonFillColors(btnColor, #D6D9FF); hScroll.setButtonFillColors(btnColor, #D6D9FF); } // setupScrollSketch /** * Displays the two scrollbars. */ // ScrollSketch void display() { if (!visible) return; if (enabled) fill(0x00FFFFFF); // use transparent color for visiblePanel else fill(DISABLED_COLOR); fill(vScroll.c[0]); rect(winPaneWidth, winPaneHeight, BAR_SIZE, BAR_SIZE); vScroll.display(); hScroll.display(); } // display /** * Sets the meter as being visible true or false. */ // ScrollSketch void setVisible(boolean b) { vScroll.setVisible(b); hScroll.setVisible(b); visible = b; } // setVisible /** * Sets the meter as being enabled true or false. */ // ScrollSketch void setEnabled(boolean b) { vScroll.setEnabled(b); hScroll.setEnabled(b); enabled = b; } // setEnabled /** * Determines if the cursor is over either of the ScrollBars * and returns true if so. Always returns false if stillSearching_ * is false. */ // ScrollSketch boolean isOver() { boolean b; b = false; if (visible && enabled) { if (!stillSearching_) return false;; if (vScroll.isOver()) { over = true; b = true; } else if (hScroll.isOver()) { over = true; b = true; } } return b; } // isOver /** * Checks to see if any part of either scrollbar has been * clicked. If so, it updates the value of soX_ or soY_ * as appropriate. Returns true if either has been clicked. * Called directly or indirectly in the mouseReleased() method. */ // ScrollSketch boolean checkForClick() { boolean b; b = false; if (visible && enabled) { if (vScroll.checkForClick()) { b = true; soY_ = (int)vScroll.getValue(); } else if (hScroll.checkForClick()){ b = true; soX_ = (int)hScroll.getValue(); } } if (b) clicked = true; return b; } // checkForClick /** * Determines if either ScrollBar has been clicked. If so, return true. * true. "clicked" is set to false. Called directly or indirectly * in by the draw() method. */ // ScrollSketch boolean hasBeenClicked(){ boolean b; b = vScroll.hasBeenClicked(); if (!b) b = hScroll.hasBeenClicked(); clicked = false; return b; } // hasBeenClicked /** * Determines if either Scroller button has experienced a * mousePressed event and could be dragged. Ignores clicks on the * bars outside of the button. Sets the position of the appropriate * scrollbutton and then sets the minimumForDrag to 0 and the drag * boundaries to appropriate scrollbar. Called from mousePressed(). */ // ScrollSketch boolean readyForDrag(Dragger theTracker) { canBeDragged = null; // reset these values in case they have been changed by declaring // the Dragger after the ScrollSketch has been declared. scrollW_ = localScrollW; scrollH_ = localScrollH; if (vScroll.over && vScroll.scrollBtn.over) { canBeDragged = vScroll.scrollBtn; theTracker.track(0, vScroll.getButtonPos()); theTracker.setSubItemTracked(vScroll); return true; } else if (hScroll.over && hScroll.scrollBtn.over){ canBeDragged = hScroll.scrollBtn; theTracker.track(hScroll.getButtonPos(), 0); theTracker.setSubItemTracked(hScroll); return true; } return false; } // readyForDrag /** * If the ScrollSketch is the current draggable item, it moves the * appropriate button and returns true after updating the value of * soY_ or soX_. It is called by mouseDragged(). */ // ScrollSketch boolean moved(Dragger theTracker) { if (theTracker.getItemTracked() != this) { return false; } theTracker.updateDrag(); if (canBeDragged == vScroll.scrollBtn) { vScroll.moved(theTracker); vScroll.setScrollBtnPos(theTracker.getUpdatedY()); soY_ = (int)vScroll.getValue(); return true; } else if (canBeDragged == hScroll.scrollBtn) { hScroll.moved(theTracker); hScroll.setScrollBtnPos(theTracker.getUpdatedX()); soX_ = (int)hScroll.getValue(); return true; } return false; } // moved /** * Returns the soX_ which is to be subtracted from * the x coordinate of scrolled things. */ // ScrollSketch int getOffsetX() { return soX_; } // getOffsetX /** * Returns the sY_ which is to be subtracted from * the y coordinate of scrolled things */ // ScrollSketch int getOffsetY() { return soY_; } // getOffsetY /** * Sets processClicks variables into the two ScrollBars. Overrides * the standard method in Draggable. */ // ScrollSketch void setProcessClicks(boolean clicks) { processClicks = clicks; vScroll.setProcessClicks(clicks); hScroll.setProcessClicks(clicks); } // setScrollSketch } // class ScrollSketch