|
- /*
- ==============================================================================
-
- This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
-
- JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2007 by Julian Storer.
-
- ------------------------------------------------------------------------------
-
- JUCE and JUCETICE can be redistributed and/or modified 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.
-
- JUCE and JUCETICE are distributed in the hope that they 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 JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-
- ==============================================================================
- */
-
- BEGIN_JUCE_NAMESPACE
-
- //==============================================================================
- Joystick::Joystick()
- : Component ("Joystick"),
- current_x (0),
- current_y (0),
- x_min (0),
- x_max (1),
- y_min (0),
- y_max (1),
- backgroundColour (Colours::black),
- sendChangeOnlyOnRelease (false),
- holdOnMouseRelease (false),
- isVelocityBased (false),
- menuEnabled (true),
- menuShown (false),
- mouseWasHidden (false),
- numDecimalPlaces (4)
- {
- setOpaque (true);
- setWantsKeyboardFocus (true);
-
- calculateRatio();
- calculateSnapBack();
- }
-
- Joystick::~Joystick()
- {
- deleteAllChildren();
- }
-
- //==============================================================================
- void Joystick::resized()
- {
- x_ratio = getWidth() / (float) (x_max - x_min);
- y_ratio = getHeight() / (float) (y_max - y_min);
-
- calculateDrawingSpot();
- }
-
- //==============================================================================
- const String Joystick::getCurrentValueAsString()
- {
- String text;
- text << getTextFromValue (current_x+x_min) << ", " << getTextFromValue (((y_max-y_min)-current_y)+y_min) ;
- return text;
- }
-
- //==============================================================================
- void Joystick::setVelocityBasedMode (const bool velBased)
- {
- isVelocityBased = velBased;
- }
-
- void Joystick::setPopupMenuEnabled (const bool menuEnabled_)
- {
- menuEnabled = menuEnabled_;
- }
-
- //==============================================================================
- void Joystick::setRanges (const double newHorizontalMin,
- const double newHorizontalMax,
- const double newVerticalMin,
- const double newVerticalMax,
- const double newInt)
- {
- bool horizontalChanged = false;
- bool verticalChanged = false;
-
- if (x_min != newHorizontalMin
- || x_max != newVerticalMax)
- {
- x_min = newHorizontalMin;
- x_max = newHorizontalMax;
- horizontalChanged = true;
- }
-
- if (y_min != newVerticalMin
- || y_max != newVerticalMax)
- {
- y_min = newVerticalMin;
- y_max = newVerticalMax;
- verticalChanged = true;
- }
-
- // figure out the number of DPs needed to display all values at this
- // interval setting.
- interval = newInt;
- numDecimalPlaces = 7;
- if (newInt != 0)
- {
- int v = abs ((int) (newInt * 10000000));
- while ((v % 10) == 0)
- {
- --numDecimalPlaces;
- v /= 10;
- }
- }
-
- if (horizontalChanged || verticalChanged)
- setValues (current_x, current_y, false);
-
- calculateRatio();
- calculateSnapBack();
- calculateDrawingSpot();
- }
-
- void Joystick::setValues (double newHorizontalValue, double newVerticalValue,
- const bool sendUpdateMessage,
- const bool sendMessageSynchronously)
- {
- if (newHorizontalValue <= x_min || x_max <= x_min)
- {
- newHorizontalValue = x_min;
- }
- else if (newHorizontalValue >= x_max)
- {
- newHorizontalValue = x_max;
- }
- else if (interval > 0)
- {
- newHorizontalValue = x_min + interval * floor ((newHorizontalValue - x_min) / interval + 0.5);
- }
-
- if (newVerticalValue <= y_min || y_max <= y_min)
- {
- newVerticalValue = y_min;
- }
- else if (newVerticalValue >= y_max)
- {
- newVerticalValue = y_max;
- }
- else if (interval > 0)
- {
- newVerticalValue = y_min + interval * floor ((newVerticalValue - y_min) / interval + 0.5);
- }
-
- if (current_x != newHorizontalValue)
- current_x = newHorizontalValue;
-
- if (current_y != newVerticalValue)
- current_y = newVerticalValue;
-
- if (current_x != newHorizontalValue || current_y != newVerticalValue)
- {
- if (sendUpdateMessage)
- {
- if (sendMessageSynchronously)
- sendChanges();
- else
- jassertfalse; // asyncronous message not implemented !
-
- valueChanged (current_x, current_y);
- }
-
- calculateDrawingSpot();
- }
- }
-
- //==============================================================================
- void Joystick::paint (Graphics& g)
- {
- // Draw main section of box ------------------------
- g.setColour (backgroundColour);
- g.fillAll ();
-
- // Determine the location of the snapback square ---
- int snap_x = roundDoubleToInt (floor (x_snap * x_ratio));
- int snap_y = roundDoubleToInt (floor (y_snap * y_ratio));
-
- // if at max value, don't go over edge
- if (x_snap == x_min) snap_x++;
- if (y_snap == x_min) snap_y++;
- if (x_snap == (x_max - x_min)) snap_x--;
- if (y_snap == (x_max - x_min)) snap_y--;
-
- // Draw the snapback square ------------------------
- g.setColour (Colours::lightyellow);
- // g.fillEllipse(snap_x-2,snap_y-2,5,5);
- g.drawEllipse (snap_x - 4, snap_y - 4, 9, 9, 1.0);
-
- // Draw the main dot -------------------------------
- if (holdOnMouseRelease)
- g.setColour (Colours::lightblue);
- else
- g.setColour (Colours::orange);
-
- g.fillEllipse (draw_x - 2, draw_y - 2, 5, 5);
- g.drawEllipse (draw_x - 4, draw_y - 4, 9, 9, 1.0);
-
- // Draw inset bevel --------------------------------
- LookAndFeel_V2::drawBevel (g,
- 0, 0,
- getWidth(), getHeight(),
- 2,
- insetDarkColour,
- insetLightColour,
- true);
- }
-
- //==============================================================================
- void Joystick::mouseDown(const MouseEvent& e)
- {
- mouseWasHidden = false;
-
- if (isEnabled())
- {
- if (e.mods.isPopupMenu() && menuEnabled)
- {
- menuShown = true;
-
- PopupMenu m;
- m.addItem (1, TRANS ("velocity-sensitive mode"), true, isVelocityBased);
- m.addSeparator();
-
- const int r = m.show();
- if (r == 1)
- {
- setVelocityBasedMode (! isVelocityBased);
- }
- else if (r == 2)
- {
- // setSliderStyle (RotaryHorizontalDrag);
- }
- else if (r == 3)
- {
- // setSliderStyle (RotaryVerticalDrag);
- }
- }
- else if (e.mods.isLeftButtonDown()
- || e.mods.isMiddleButtonDown())
- {
- menuShown = false;
-
- // unbound mouse movements
- if (isVelocityBased)
- {
- e.source.enableUnboundedMouseMovement (true, false);
- mouseWasHidden = true;
- }
-
- startPressX = e.x;
- startPressY = e.y;
-
- // In case it was a click without a drag, do the drag anyway
- mouseDrag (e);
- }
-
- // So arrow keys works
- grabKeyboardFocus();
- }
- }
-
- void Joystick::mouseDrag (const MouseEvent& e) //Called continuously while moving mouse
- {
- if (isEnabled() && ! menuShown)
- {
- // If shift is down, don't allow changes to the X value
- if (! e.mods.isShiftDown())
- {
- //Determine current X value based on mouse location
- int x = startPressX + e.getDistanceFromDragStartX ();
- if (x < 0)
- current_x = 0;
- else if (x >= getWidth())
- current_x = x_max - x_min;
- else
- current_x = x / x_ratio;
- }
-
- // If ctrl is down, don't allow changes to Y value
- if (! e.mods.isCtrlDown())
- {
- //Determine current Y value based on mouse location
- int y = startPressY + e.getDistanceFromDragStartY ();
- if (y < 0)
- current_y = 0;
- else if (y > getHeight())
- current_y = y_max - y_min;
- else
- current_y = y / y_ratio;
- }
-
- // If holding down control key, then set snapback values
- if (e.mods.isLeftButtonDown())
- {
- x_snap = current_x;
- y_snap = current_y;
- }
-
- // If right left is down, then hold
- if (e.mods.isLeftButtonDown())
- holdOnMouseRelease = true;
- else
- holdOnMouseRelease = false;
-
- // Send changes and repaint screen
- if (! sendChangeOnlyOnRelease)
- {
- valueChanged (current_x, current_y);
- sendChanges ();
- }
-
- // update drawing position
- calculateDrawingSpot();
-
- repaint ();
- }
- }
-
-
- void Joystick::mouseUp (const MouseEvent& e) //Called when the mouse button is released
- {
- if (isEnabled() && ! menuShown)
- {
- // If not holding, then jump to snapback values
- if (! holdOnMouseRelease)
- {
- current_x = x_snap;
- current_y = y_snap;
- }
-
- // Call user defined callback
- valueChanged (current_x, current_y);
-
- // Send controllers changes values
- sendChanges ();
-
- // update drawing position
- calculateDrawingSpot();
-
- // restore mouse
- restoreMouseIfHidden();
-
- repaint ();
- }
- }
-
- void Joystick::mouseMove (const MouseEvent& e)
- {
- }
-
- //==============================================================================
- bool Joystick::keyPressed (const KeyPress& key)
- {
- if (key.isKeyCode (KeyPress::upKey))
- {
- setValues(current_x,current_y-interval);
- }
- else if (key.isKeyCode (KeyPress::downKey))
- {
- setValues(current_x,current_y+interval);
- }
- else if (key.isKeyCode (KeyPress::leftKey))
- {
- setValues(current_x-interval,current_y);
- }
- else if (key.isKeyCode (KeyPress::rightKey))
- {
- setValues(current_x+interval,current_y);
- }
- else
- {
- return Component::keyPressed (key);
- }
-
- return true;
- }
-
- bool Joystick::keyStateChanged(const bool keyDown)
- {
- // only forward key events that aren't used by this component
- if (keyDown &&
- ! (KeyPress::isKeyCurrentlyDown (KeyPress::upKey)
- || KeyPress::isKeyCurrentlyDown (KeyPress::leftKey)
- || KeyPress::isKeyCurrentlyDown (KeyPress::downKey)
- || KeyPress::isKeyCurrentlyDown (KeyPress::rightKey)))
- {
- return Component::keyStateChanged(keyDown);
- }
-
- return false;
- }
-
- //==============================================================================
- void Joystick::addListener (JoystickListener* const listener)
- {
- jassert (listener != 0);
- if (listener != 0)
- listeners.add (listener);
- }
-
- void Joystick::removeListener (JoystickListener* const listener)
- {
- int index = listeners.indexOf (listener);
- if (index >= 0)
- listeners.remove (index);
- }
-
- void Joystick::sendChanges()
- {
- for (int i = listeners.size (); --i >= 0;)
- ((JoystickListener*) listeners.getUnchecked (i))->joystickValueChanged (this);
- }
-
- //==============================================================================
- void Joystick::calculateRatio()
- {
- // Calculate the x and y ratio
- x_ratio = getWidth() / (float) (x_max - x_min);
- y_ratio = getHeight() / (float) (y_max - y_min);
- }
-
- void Joystick::calculateSnapBack()
- {
- // Calculate the new snapback values based on the min and max
- // x_snap = roundDoubleToInt(floor((x_max-x_min)/2.0));
- // y_snap = roundDoubleToInt(floor((y_max-y_min)/2.0));
-
- x_snap = (x_max - x_min) / 2.0;
- y_snap = (y_max - y_min) / 2.0;
-
- // If the range is odd, then add 1 to X to calculate center correctly (HACK!)
- // if (roundDoubleToInt(x_max-x_min) % 2 != 0)
- // x_snap++;
-
- // Set the current location to the snapback
- current_x = x_snap;
- current_y = y_snap;
- }
-
- void Joystick::calculateDrawingSpot()
- {
- // Determine the current drawing location
- draw_x = roundDoubleToInt (floor (current_x * x_ratio));
- draw_y = roundDoubleToInt (floor (current_y * y_ratio));
-
- // If at max value, don't go over edge
- if (current_x == x_min) draw_x++;
- if (current_y == y_min) draw_y++;
- if (current_x == (x_max - x_min)) draw_x--;
- if (current_y == (y_max - y_min)) draw_y--;
- }
-
- const String Joystick::getTextFromValue (double v)
- {
- if (numDecimalPlaces > 0)
- return String (v, numDecimalPlaces);
- else
- return String (roundDoubleToInt (v));
- }
-
- //==============================================================================
- void Joystick::restoreMouseIfHidden()
- {
- if (mouseWasHidden)
- {
- mouseWasHidden = false;
-
- /*Component* c = Component::getComponentUnderMouse();
- if (c == 0)
- c = this;
- c->enableUnboundedMouseMovement (false);*/
-
- Point<int> p (getScreenX() + draw_x,
- getScreenY() + draw_y);
-
- Desktop::setMousePosition (p);
- }
- }
-
- //==============================================================================
- void Joystick::startedDragging()
- {
- }
-
- void Joystick::stoppedDragging()
- {
- }
-
- void Joystick::valueChanged (double x, double y)
- {
- }
- END_JUCE_NAMESPACE
-
|