mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
1426 lines
54 KiB
C++
1426 lines
54 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
|
Copyright 2004-9 by Raw Material Software Ltd.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
JUCE can be redistributed and/or modified under the terms of the GNU General
|
|
Public License (Version 2), as published by the Free Software Foundation.
|
|
A copy of the license is included in the JUCE distribution, or can be found
|
|
online at www.gnu.org/licenses.
|
|
|
|
JUCE 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.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
To release a closed-source product which uses JUCE, commercial licenses are
|
|
available: visit www.rawmaterialsoftware.com/juce for more information.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#include "../jucedemo_headers.h"
|
|
|
|
|
|
//==============================================================================
|
|
class BouncingBallComponent : public Component,
|
|
public Timer
|
|
{
|
|
public:
|
|
BouncingBallComponent()
|
|
{
|
|
x = Random::getSystemRandom().nextFloat() * 100.0f;
|
|
y = Random::getSystemRandom().nextFloat() * 100.0f;
|
|
|
|
dx = Random::getSystemRandom().nextFloat() * 8.0f - 4.0f;
|
|
dy = Random::getSystemRandom().nextFloat() * 8.0f - 4.0f;
|
|
|
|
colour = Colour (Random::getSystemRandom().nextInt())
|
|
.withAlpha (0.5f)
|
|
.withBrightness (0.7f);
|
|
|
|
int size = 10 + Random::getSystemRandom().nextInt (30);
|
|
setSize (size, size);
|
|
|
|
startTimer (60);
|
|
}
|
|
|
|
~BouncingBallComponent()
|
|
{
|
|
}
|
|
|
|
void paint (Graphics& g)
|
|
{
|
|
g.setColour (colour);
|
|
g.fillEllipse (x - getX(), y - getY(), getWidth() - 2.0f, getHeight() - 2.0f);
|
|
}
|
|
|
|
void timerCallback()
|
|
{
|
|
x += dx;
|
|
y += dy;
|
|
|
|
if (x < 0)
|
|
dx = fabsf (dx);
|
|
|
|
if (x > getParentWidth())
|
|
dx = -fabsf (dx);
|
|
|
|
if (y < 0)
|
|
dy = fabsf (dy);
|
|
|
|
if (y > getParentHeight())
|
|
dy = -fabsf (dy);
|
|
|
|
setTopLeftPosition ((int) x, (int) y);
|
|
}
|
|
|
|
bool hitTest (int /*x*/, int /*y*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
Colour colour;
|
|
float x, y, dx, dy;
|
|
};
|
|
|
|
//==============================================================================
|
|
class DragOntoDesktopDemoComp : public Component
|
|
{
|
|
public:
|
|
DragOntoDesktopDemoComp (Component* p)
|
|
: parent (p)
|
|
{
|
|
// show off semi-transparency if it's supported by the current OS.
|
|
setOpaque (! Desktop::canUseSemiTransparentWindows());
|
|
|
|
for (int i = 0; i < numElementsInArray (balls); ++i)
|
|
addAndMakeVisible (&(balls[i]));
|
|
}
|
|
|
|
~DragOntoDesktopDemoComp()
|
|
{
|
|
}
|
|
|
|
void mouseDown (const MouseEvent& e)
|
|
{
|
|
dragger.startDraggingComponent (this, e);
|
|
}
|
|
|
|
void mouseDrag (const MouseEvent& e)
|
|
{
|
|
if (parent == 0)
|
|
{
|
|
delete this; // If our parent has been deleted, we'll just get rid of this component
|
|
}
|
|
else
|
|
{
|
|
// if the mouse is inside the parent component, we'll make that the
|
|
// parent - otherwise, we'll put this comp on the desktop.
|
|
if (parent->getLocalBounds().contains (e.getEventRelativeTo (parent).getPosition()))
|
|
{
|
|
// re-add this component to a parent component, which will
|
|
// remove it from the desktop..
|
|
parent->addChildComponent (this);
|
|
}
|
|
else
|
|
{
|
|
// add the component to the desktop, which will remove it
|
|
// from its current parent component..
|
|
addToDesktop (ComponentPeer::windowIsTemporary);
|
|
}
|
|
|
|
dragger.dragComponent (this, e, 0);
|
|
}
|
|
}
|
|
|
|
void paint (Graphics& g)
|
|
{
|
|
if (isOpaque())
|
|
g.fillAll (Colours::white);
|
|
else
|
|
g.fillAll (Colours::blue.withAlpha (0.2f));
|
|
|
|
String desc ("drag this box onto the desktop to show how the same component can move from being lightweight to being a separate window");
|
|
|
|
g.setFont (15.0f);
|
|
g.setColour (Colours::black);
|
|
g.drawFittedText (desc, 4, 0, getWidth() - 8, getHeight(), Justification::horizontallyJustified, 5);
|
|
|
|
g.drawRect (0, 0, getWidth(), getHeight());
|
|
}
|
|
|
|
private:
|
|
Component::SafePointer<Component> parent; // A safe-pointer will become zero if the component that it refers to is deleted..
|
|
ComponentDragger dragger;
|
|
|
|
BouncingBallComponent balls[3];
|
|
};
|
|
|
|
//==============================================================================
|
|
class CustomMenuComponent : public PopupMenuCustomComponent,
|
|
public Timer
|
|
{
|
|
public:
|
|
CustomMenuComponent()
|
|
: blobX (0),
|
|
blobY (0)
|
|
{
|
|
// set off a timer to move a blob around on this component every
|
|
// 300 milliseconds - see the timerCallback() method.
|
|
startTimer (300);
|
|
}
|
|
|
|
~CustomMenuComponent()
|
|
{
|
|
}
|
|
|
|
void getIdealSize (int& idealWidth,
|
|
int& idealHeight)
|
|
{
|
|
// tells the menu how big we'd like to be..
|
|
idealWidth = 200;
|
|
idealHeight = 60;
|
|
}
|
|
|
|
void paint (Graphics& g)
|
|
{
|
|
g.fillAll (Colours::yellow.withAlpha (0.3f));
|
|
|
|
g.setColour (Colours::pink);
|
|
g.fillEllipse ((float) blobX, (float) blobY, 30.0f, 40.0f);
|
|
|
|
g.setFont (14.0f, Font::italic);
|
|
g.setColour (Colours::black);
|
|
|
|
g.drawFittedText ("this is a customised menu item (also demonstrating the Timer class)...",
|
|
4, 0, getWidth() - 8, getHeight(),
|
|
Justification::centred, 3);
|
|
}
|
|
|
|
void timerCallback()
|
|
{
|
|
blobX = Random::getSystemRandom().nextInt (getWidth());
|
|
blobY = Random::getSystemRandom().nextInt (getHeight());
|
|
repaint();
|
|
}
|
|
|
|
private:
|
|
int blobX, blobY;
|
|
};
|
|
|
|
//==============================================================================
|
|
/** To demonstrate how sliders can have custom snapping applied to their values,
|
|
this simple class snaps the value to 50 if it comes near.
|
|
*/
|
|
class SnappingSlider : public Slider
|
|
{
|
|
public:
|
|
SnappingSlider (const String& name)
|
|
: Slider (name)
|
|
{
|
|
}
|
|
|
|
double snapValue (double attemptedValue, bool userIsDragging)
|
|
{
|
|
if (! userIsDragging)
|
|
return attemptedValue; // if they're entering the value in the text-box, don't mess with it.
|
|
|
|
if (attemptedValue > 40 && attemptedValue < 60)
|
|
return 50.0;
|
|
else
|
|
return attemptedValue;
|
|
}
|
|
};
|
|
|
|
/** A TextButton that pops up a colour chooser to change its colours. */
|
|
class ColourChangeButton : public TextButton,
|
|
public ChangeListener
|
|
{
|
|
public:
|
|
ColourChangeButton()
|
|
: TextButton ("click to change colour...")
|
|
{
|
|
setSize (10, 24);
|
|
changeWidthToFitText();
|
|
}
|
|
|
|
~ColourChangeButton()
|
|
{
|
|
}
|
|
|
|
void clicked()
|
|
{
|
|
// create two colour selector components for our background and
|
|
// text colour..
|
|
ColourSelector colourSelector;
|
|
colourSelector.setName ("background");
|
|
colourSelector.setCurrentColour (findColour (TextButton::buttonColourId));
|
|
colourSelector.addChangeListener (this);
|
|
colourSelector.setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
|
|
colourSelector.setSize (300, 400);
|
|
|
|
CallOutBox callOut (colourSelector, *this, 0);
|
|
callOut.runModalLoop();
|
|
}
|
|
|
|
void changeListenerCallback (ChangeBroadcaster* source)
|
|
{
|
|
ColourSelector* cs = dynamic_cast <ColourSelector*> (source);
|
|
|
|
setColour (TextButton::buttonColourId, cs->getCurrentColour());
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
/* A component to act as a simple container for our demos, which deletes all the child
|
|
components that we stuff into it.
|
|
*/
|
|
class DemoPageComp : public Component
|
|
{
|
|
public:
|
|
DemoPageComp()
|
|
{
|
|
}
|
|
|
|
~DemoPageComp()
|
|
{
|
|
/* Deleting your child components indiscriminately using deleteAllChildren() is not recommended! It's much
|
|
safer to make them embedded members or use ScopedPointers to automatically manage their lifetimes!
|
|
|
|
In this demo, where we're throwing together a whole bunch of random components, it's simpler to do it
|
|
like this, but don't treat this as an example of good practice!
|
|
*/
|
|
deleteAllChildren();
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
static Component* createSlidersPage()
|
|
{
|
|
DemoPageComp* page = new DemoPageComp();
|
|
|
|
const int numSliders = 11;
|
|
Slider* sliders [numSliders];
|
|
|
|
int i;
|
|
for (i = 0; i < numSliders; ++i)
|
|
{
|
|
if (i == 2)
|
|
page->addAndMakeVisible (sliders[i] = new SnappingSlider ("slider"));
|
|
else
|
|
page->addAndMakeVisible (sliders[i] = new Slider ("slider"));
|
|
|
|
sliders[i]->setRange (0.0, 100.0, 0.1);
|
|
sliders[i]->setPopupMenuEnabled (true);
|
|
sliders[i]->setValue (Random::getSystemRandom().nextDouble() * 100.0, false, false);
|
|
}
|
|
|
|
sliders[0]->setSliderStyle (Slider::LinearVertical);
|
|
sliders[0]->setTextBoxStyle (Slider::TextBoxBelow, false, 100, 20);
|
|
sliders[0]->setBounds (10, 25, 70, 200);
|
|
sliders[0]->setDoubleClickReturnValue (true, 50.0); // double-clicking this slider will set it to 50.0
|
|
sliders[0]->setTextValueSuffix (" units");
|
|
|
|
sliders[1]->setSliderStyle (Slider::LinearVertical);
|
|
sliders[1]->setVelocityBasedMode (true);
|
|
sliders[1]->setSkewFactor (0.5);
|
|
sliders[1]->setTextBoxStyle (Slider::TextBoxAbove, true, 100, 20);
|
|
sliders[1]->setBounds (85, 25, 70, 200);
|
|
sliders[1]->setTextValueSuffix (" rels");
|
|
|
|
sliders[2]->setSliderStyle (Slider::LinearHorizontal);
|
|
sliders[2]->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
|
|
sliders[2]->setBounds (180, 35, 150, 20);
|
|
|
|
sliders[3]->setSliderStyle (Slider::LinearHorizontal);
|
|
sliders[3]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0);
|
|
sliders[3]->setBounds (180, 65, 150, 20);
|
|
sliders[3]->setPopupDisplayEnabled (true, page);
|
|
sliders[3]->setTextValueSuffix (" nuns required to change a lightbulb");
|
|
|
|
sliders[4]->setSliderStyle (Slider::IncDecButtons);
|
|
sliders[4]->setTextBoxStyle (Slider::TextBoxLeft, false, 50, 20);
|
|
sliders[4]->setBounds (180, 105, 100, 20);
|
|
sliders[4]->setIncDecButtonsMode (Slider::incDecButtonsDraggable_Vertical);
|
|
|
|
sliders[5]->setSliderStyle (Slider::Rotary);
|
|
sliders[5]->setRotaryParameters (float_Pi * 1.2f, float_Pi * 2.8f, false);
|
|
sliders[5]->setTextBoxStyle (Slider::TextBoxRight, false, 70, 20);
|
|
sliders[5]->setBounds (190, 145, 120, 40);
|
|
sliders[5]->setTextValueSuffix (" mm");
|
|
|
|
sliders[6]->setSliderStyle (Slider::LinearBar);
|
|
sliders[6]->setBounds (180, 195, 100, 30);
|
|
sliders[6]->setTextValueSuffix (" gallons");
|
|
|
|
sliders[7]->setSliderStyle (Slider::TwoValueHorizontal);
|
|
sliders[7]->setBounds (360, 20, 160, 40);
|
|
|
|
sliders[8]->setSliderStyle (Slider::TwoValueVertical);
|
|
sliders[8]->setBounds (360, 110, 40, 160);
|
|
|
|
sliders[9]->setSliderStyle (Slider::ThreeValueHorizontal);
|
|
sliders[9]->setBounds (360, 70, 160, 40);
|
|
|
|
sliders[10]->setSliderStyle (Slider::ThreeValueVertical);
|
|
sliders[10]->setBounds (440, 110, 40, 160);
|
|
|
|
for (i = 7; i <= 10; ++i)
|
|
{
|
|
sliders[i]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0);
|
|
sliders[i]->setPopupDisplayEnabled (true, page);
|
|
}
|
|
|
|
/* Here, we'll create a Value object, and tell a bunch of our sliders to use it as their
|
|
value source. By telling them all to share the same Value, they'll stay in sync with
|
|
each other.
|
|
|
|
We could also optionally keep a copy of this Value elsewhere, and by changing it,
|
|
cause all the sliders to automatically update.
|
|
*/
|
|
Value sharedValue;
|
|
sharedValue = Random::getSystemRandom().nextDouble() * 100;
|
|
for (i = 0; i < 7; ++i)
|
|
sliders[i]->getValueObject().referTo (sharedValue);
|
|
|
|
// ..and now we'll do the same for all our min/max slider values..
|
|
Value sharedValueMin, sharedValueMax;
|
|
sharedValueMin = Random::getSystemRandom().nextDouble() * 40.0;
|
|
sharedValueMax = Random::getSystemRandom().nextDouble() * 40.0 + 60.0;
|
|
|
|
for (i = 7; i <= 10; ++i)
|
|
{
|
|
sliders[i]->getMaxValueObject().referTo (sharedValueMax);
|
|
sliders[i]->getMinValueObject().referTo (sharedValueMin);
|
|
}
|
|
|
|
// Create a description label...
|
|
Label* label = new Label ("hint", "Try right-clicking on a slider for an options menu. \n\nAlso, holding down CTRL while dragging will turn on a slider's velocity-sensitive mode");
|
|
label->setBounds (20, 245, 350, 150);
|
|
page->addAndMakeVisible (label);
|
|
|
|
return page;
|
|
}
|
|
|
|
//==============================================================================
|
|
static Component* createRadioButtonPage()
|
|
{
|
|
DemoPageComp* page = new DemoPageComp();
|
|
|
|
GroupComponent* group = new GroupComponent ("group", "radio buttons");
|
|
group->setBounds (20, 20, 220, 140);
|
|
page->addAndMakeVisible (group);
|
|
|
|
int i;
|
|
for (i = 0; i < 4; ++i)
|
|
{
|
|
ToggleButton* tb = new ToggleButton ("radio button #" + String (i + 1));
|
|
page->addAndMakeVisible (tb);
|
|
tb->setRadioGroupId (1234);
|
|
tb->setBounds (45, 46 + i * 22, 180, 22);
|
|
tb->setTooltip ("a set of mutually-exclusive radio buttons");
|
|
|
|
if (i == 0)
|
|
tb->setToggleState (true, false);
|
|
}
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
{
|
|
DrawablePath normal, over;
|
|
|
|
Path p;
|
|
p.addStar (Point<float>(), i + 5, 20.0f, 50.0f, -0.2f);
|
|
normal.setPath (p);
|
|
normal.setFill (Colours::lightblue);
|
|
normal.setStrokeFill (Colours::black);
|
|
normal.setStrokeThickness (4.0f);
|
|
|
|
over.setPath (p);
|
|
over.setFill (Colours::blue);
|
|
over.setStrokeFill (Colours::black);
|
|
over.setStrokeThickness (4.0f);
|
|
|
|
DrawableButton* db = new DrawableButton (String (i + 5) + " points", DrawableButton::ImageAboveTextLabel);
|
|
db->setImages (&normal, &over, 0);
|
|
|
|
page->addAndMakeVisible (db);
|
|
db->setClickingTogglesState (true);
|
|
db->setRadioGroupId (23456);
|
|
|
|
const int buttonSize = 50;
|
|
db->setBounds (25 + i * buttonSize, 180, buttonSize, buttonSize);
|
|
|
|
if (i == 0)
|
|
db->setToggleState (true, false);
|
|
}
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
{
|
|
TextButton* tb = new TextButton ("button " + String (i + 1));
|
|
|
|
page->addAndMakeVisible (tb);
|
|
tb->setClickingTogglesState (true);
|
|
tb->setRadioGroupId (34567);
|
|
tb->setColour (TextButton::buttonColourId, Colours::white);
|
|
tb->setColour (TextButton::buttonOnColourId, Colours::blueviolet.brighter());
|
|
|
|
tb->setBounds (20 + i * 55, 260, 55, 24);
|
|
tb->setConnectedEdges (((i != 0) ? Button::ConnectedOnLeft : 0)
|
|
| ((i != 3) ? Button::ConnectedOnRight : 0));
|
|
|
|
if (i == 0)
|
|
tb->setToggleState (true, false);
|
|
}
|
|
|
|
return page;
|
|
}
|
|
|
|
//==============================================================================
|
|
class ButtonsPage : public Component,
|
|
public ButtonListener
|
|
{
|
|
public:
|
|
ButtonsPage (ButtonListener* buttonListener)
|
|
{
|
|
//==============================================================================
|
|
// create some drawables to use for our drawable buttons...
|
|
DrawablePath normal, over;
|
|
|
|
Path p;
|
|
p.addStar (Point<float>(), 5, 20.0f, 50.0f, 0.2f);
|
|
normal.setPath (p);
|
|
normal.setFill (Colours::red);
|
|
|
|
p.clear();
|
|
p.addStar (Point<float>(), 7, 30.0f, 50.0f, 0.0f);
|
|
over.setPath (p);
|
|
over.setFill (Colours::pink);
|
|
over.setStrokeFill (Colours::black);
|
|
over.setStrokeThickness (5.0f);
|
|
|
|
DrawableImage down;
|
|
down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize));
|
|
down.setOverlayColour (Colours::black.withAlpha (0.3f));
|
|
|
|
//==============================================================================
|
|
// create an image-above-text button from these drawables..
|
|
DrawableButton* db = new DrawableButton ("Button 1", DrawableButton::ImageAboveTextLabel);
|
|
db->setImages (&normal, &over, &down);
|
|
|
|
addAndMakeVisible (db);
|
|
db->setBounds (10, 30, 80, 80);
|
|
db->setTooltip ("this is a DrawableButton with a label");
|
|
|
|
//==============================================================================
|
|
// create an image-only button from these drawables..
|
|
db = new DrawableButton ("Button 2", DrawableButton::ImageFitted);
|
|
db->setImages (&normal, &over, &down);
|
|
db->setClickingTogglesState (true);
|
|
|
|
addAndMakeVisible (db);
|
|
db->setBounds (90, 30, 80, 80);
|
|
db->setTooltip ("this is an image-only DrawableButton");
|
|
db->addListener (buttonListener);
|
|
|
|
//==============================================================================
|
|
// create an image-on-button-shape button from the same drawables..
|
|
db = new DrawableButton ("Button 3", DrawableButton::ImageOnButtonBackground);
|
|
db->setImages (&normal, 0, 0);
|
|
|
|
addAndMakeVisible (db);
|
|
db->setBounds (200, 30, 110, 25);
|
|
db->setTooltip ("this is a DrawableButton on a standard button background");
|
|
|
|
//==============================================================================
|
|
db = new DrawableButton ("Button 4", DrawableButton::ImageOnButtonBackground);
|
|
db->setImages (&normal, &over, &down);
|
|
db->setClickingTogglesState (true);
|
|
db->setBackgroundColours (Colours::white, Colours::yellow);
|
|
|
|
addAndMakeVisible (db);
|
|
db->setBounds (200, 70, 50, 50);
|
|
db->setTooltip ("this is a DrawableButton on a standard button background");
|
|
db->addListener (buttonListener);
|
|
|
|
//==============================================================================
|
|
HyperlinkButton* hyperlink
|
|
= new HyperlinkButton ("this is a HyperlinkButton",
|
|
URL ("http://www.rawmaterialsoftware.com/juce"));
|
|
|
|
hyperlink->setBounds (10, 130, 200, 24);
|
|
addAndMakeVisible (hyperlink);
|
|
|
|
//==============================================================================
|
|
ImageButton* imageButton = new ImageButton ("imagebutton");
|
|
addAndMakeVisible (imageButton);
|
|
|
|
Image juceImage = ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize);
|
|
imageButton->setImages (true, true, true,
|
|
juceImage, 0.7f, Colours::transparentBlack,
|
|
juceImage, 1.0f, Colours::transparentBlack,
|
|
juceImage, 1.0f, Colours::pink.withAlpha (0.8f),
|
|
0.5f);
|
|
|
|
imageButton->setTopLeftPosition (10, 160);
|
|
imageButton->setTooltip ("image button - showing alpha-channel hit-testing and colour overlay when clicked");
|
|
|
|
//==============================================================================
|
|
ColourChangeButton* colourChangeButton = new ColourChangeButton();
|
|
addAndMakeVisible (colourChangeButton);
|
|
colourChangeButton->setTopLeftPosition (350, 30);
|
|
|
|
//==============================================================================
|
|
animateButton = new TextButton ("click to animate...");
|
|
addAndMakeVisible (animateButton);
|
|
animateButton->changeWidthToFitText (24);
|
|
animateButton->setTopLeftPosition (350, 70);
|
|
animateButton->addListener (this);
|
|
}
|
|
|
|
~ButtonsPage()
|
|
{
|
|
/* Deleting your child components indiscriminately using deleteAllChildren() is not recommended! It's much
|
|
safer to make them embedded members or use ScopedPointers to automatically manage their lifetimes!
|
|
|
|
In this demo, where we're throwing together a whole bunch of random components, it's simpler to do it
|
|
like this, but don't treat this as an example of good practice!
|
|
*/
|
|
deleteAllChildren();
|
|
}
|
|
|
|
void buttonClicked (Button*)
|
|
{
|
|
for (int i = getNumChildComponents(); --i >= 0;)
|
|
{
|
|
if (getChildComponent (i) != animateButton)
|
|
{
|
|
animator.animateComponent (getChildComponent (i),
|
|
Rectangle<int> (Random::getSystemRandom().nextInt (getWidth() / 2),
|
|
Random::getSystemRandom().nextInt (getHeight() / 2),
|
|
60 + Random::getSystemRandom().nextInt (getWidth() / 3),
|
|
16 + Random::getSystemRandom().nextInt (getHeight() / 6)),
|
|
Random::getSystemRandom().nextFloat(),
|
|
500 + Random::getSystemRandom().nextInt (2000),
|
|
false,
|
|
Random::getSystemRandom().nextDouble(),
|
|
Random::getSystemRandom().nextDouble());
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
TextButton* animateButton;
|
|
ComponentAnimator animator;
|
|
};
|
|
|
|
|
|
//==============================================================================
|
|
static Component* createMiscPage()
|
|
{
|
|
DemoPageComp* page = new DemoPageComp();
|
|
|
|
TextEditor* textEditor1 = new TextEditor();
|
|
page->addAndMakeVisible (textEditor1);
|
|
textEditor1->setBounds (10, 25, 200, 24);
|
|
textEditor1->setText ("single-line text box");
|
|
|
|
TextEditor* textEditor2 = new TextEditor ("password", (tchar) 0x2022);
|
|
page->addAndMakeVisible (textEditor2);
|
|
textEditor2->setBounds (10, 55, 200, 24);
|
|
textEditor2->setText ("password");
|
|
|
|
//==============================================================================
|
|
ComboBox* comboBox = new ComboBox ("combo");
|
|
page->addAndMakeVisible (comboBox);
|
|
comboBox->setBounds (300, 25, 200, 24);
|
|
comboBox->setEditableText (true);
|
|
comboBox->setJustificationType (Justification::centred);
|
|
|
|
int i;
|
|
for (i = 1; i < 100; ++i)
|
|
comboBox->addItem ("combo box item " + String (i), i);
|
|
|
|
comboBox->setSelectedId (1);
|
|
|
|
DragOntoDesktopDemoComp* d = new DragOntoDesktopDemoComp (page);
|
|
page->addAndMakeVisible (d);
|
|
d->setBounds (20, 100, 200, 80);
|
|
|
|
return page;
|
|
}
|
|
|
|
//==============================================================================
|
|
class ToolbarDemoComp : public Component,
|
|
public SliderListener,
|
|
public ButtonListener
|
|
{
|
|
public:
|
|
ToolbarDemoComp()
|
|
: depthLabel (String::empty, "Toolbar depth:"),
|
|
infoLabel (String::empty, "As well as showing off toolbars, this demo illustrates how to store "
|
|
"a set of SVG files in a Zip file, embed that in your application, and read "
|
|
"them back in at runtime.\n\nThe icon images here are taken from the open-source "
|
|
"Tango icon project."),
|
|
orientationButton ("Vertical/Horizontal"),
|
|
customiseButton ("Customise...")
|
|
{
|
|
// Create and add the toolbar...
|
|
addAndMakeVisible (&toolbar);
|
|
|
|
// And use our item factory to add a set of default icons to it...
|
|
toolbar.addDefaultItems (factory);
|
|
|
|
// Now we'll just create the other sliders and buttons on the demo page, which adjust
|
|
// the toolbar's properties...
|
|
addAndMakeVisible (&infoLabel);
|
|
infoLabel.setJustificationType (Justification::topLeft);
|
|
infoLabel.setBounds (80, 80, 450, 100);
|
|
infoLabel.setInterceptsMouseClicks (false, false);
|
|
|
|
addAndMakeVisible (&depthSlider);
|
|
depthSlider.setRange (10.0, 200.0, 1.0);
|
|
depthSlider.setValue (50, false);
|
|
depthSlider.setSliderStyle (Slider::LinearHorizontal);
|
|
depthSlider.setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
|
|
depthSlider.addListener (this);
|
|
depthSlider.setBounds (80, 210, 300, 22);
|
|
depthLabel.attachToComponent (&depthSlider, false);
|
|
|
|
addAndMakeVisible (&orientationButton);
|
|
orientationButton.addListener (this);
|
|
orientationButton.changeWidthToFitText (22);
|
|
orientationButton.setTopLeftPosition (depthSlider.getX(), depthSlider.getBottom() + 20);
|
|
|
|
addAndMakeVisible (&customiseButton);
|
|
customiseButton.addListener (this);
|
|
customiseButton.changeWidthToFitText (22);
|
|
customiseButton.setTopLeftPosition (orientationButton.getRight() + 20, orientationButton.getY());
|
|
}
|
|
|
|
~ToolbarDemoComp()
|
|
{
|
|
}
|
|
|
|
void resized()
|
|
{
|
|
if (toolbar.isVertical())
|
|
toolbar.setBounds (0, 0, (int) depthSlider.getValue(), getHeight());
|
|
else
|
|
toolbar.setBounds (0, 0, getWidth(), (int) depthSlider.getValue());
|
|
}
|
|
|
|
void sliderValueChanged (Slider*)
|
|
{
|
|
resized();
|
|
}
|
|
|
|
void buttonClicked (Button* button)
|
|
{
|
|
if (button == &orientationButton)
|
|
{
|
|
toolbar.setVertical (! toolbar.isVertical());
|
|
resized();
|
|
}
|
|
else if (button == &customiseButton)
|
|
{
|
|
toolbar.showCustomisationDialog (factory);
|
|
}
|
|
}
|
|
|
|
private:
|
|
Toolbar toolbar;
|
|
Slider depthSlider;
|
|
Label depthLabel, infoLabel;
|
|
TextButton orientationButton, customiseButton;
|
|
|
|
//==============================================================================
|
|
class DemoToolbarItemFactory : public ToolbarItemFactory
|
|
{
|
|
public:
|
|
DemoToolbarItemFactory() {}
|
|
~DemoToolbarItemFactory() {}
|
|
|
|
//==============================================================================
|
|
// Each type of item a toolbar can contain must be given a unique ID. These
|
|
// are the ones we'll use in this demo.
|
|
enum DemoToolbarItemIds
|
|
{
|
|
doc_new = 1,
|
|
doc_open = 2,
|
|
doc_save = 3,
|
|
doc_saveAs = 4,
|
|
edit_copy = 5,
|
|
edit_cut = 6,
|
|
edit_paste = 7,
|
|
juceLogoButton = 8,
|
|
customComboBox = 9
|
|
};
|
|
|
|
void getAllToolbarItemIds (Array <int>& ids)
|
|
{
|
|
// This returns the complete list of all item IDs that are allowed to
|
|
// go in our toolbar. Any items you might want to add must be listed here. The
|
|
// order in which they are listed will be used by the toolbar customisation panel.
|
|
|
|
ids.add (doc_new);
|
|
ids.add (doc_open);
|
|
ids.add (doc_save);
|
|
ids.add (doc_saveAs);
|
|
ids.add (edit_copy);
|
|
ids.add (edit_cut);
|
|
ids.add (edit_paste);
|
|
ids.add (juceLogoButton);
|
|
ids.add (customComboBox);
|
|
|
|
// If you're going to use separators, then they must also be added explicitly
|
|
// to the list.
|
|
ids.add (separatorBarId);
|
|
ids.add (spacerId);
|
|
ids.add (flexibleSpacerId);
|
|
}
|
|
|
|
void getDefaultItemSet (Array <int>& ids)
|
|
{
|
|
// This returns an ordered list of the set of items that make up a
|
|
// toolbar's default set. Not all items need to be on this list, and
|
|
// items can appear multiple times (e.g. the separators used here).
|
|
ids.add (doc_new);
|
|
ids.add (doc_open);
|
|
ids.add (doc_save);
|
|
ids.add (doc_saveAs);
|
|
ids.add (spacerId);
|
|
ids.add (separatorBarId);
|
|
ids.add (edit_copy);
|
|
ids.add (edit_cut);
|
|
ids.add (edit_paste);
|
|
ids.add (separatorBarId);
|
|
ids.add (flexibleSpacerId);
|
|
ids.add (customComboBox);
|
|
ids.add (flexibleSpacerId);
|
|
ids.add (separatorBarId);
|
|
ids.add (juceLogoButton);
|
|
}
|
|
|
|
ToolbarItemComponent* createItem (int itemId)
|
|
{
|
|
switch (itemId)
|
|
{
|
|
case doc_new: return createButtonFromZipFileSVG (itemId, "new", "document-new.svg");
|
|
case doc_open: return createButtonFromZipFileSVG (itemId, "open", "document-open.svg");
|
|
case doc_save: return createButtonFromZipFileSVG (itemId, "save", "document-save.svg");
|
|
case doc_saveAs: return createButtonFromZipFileSVG (itemId, "save as", "document-save-as.svg");
|
|
case edit_copy: return createButtonFromZipFileSVG (itemId, "copy", "edit-copy.svg");
|
|
case edit_cut: return createButtonFromZipFileSVG (itemId, "cut", "edit-cut.svg");
|
|
case edit_paste: return createButtonFromZipFileSVG (itemId, "paste", "edit-paste.svg");
|
|
case juceLogoButton: return new ToolbarButton (itemId, "juce!", Drawable::createFromImageData (BinaryData::juce_png, BinaryData::juce_pngSize), 0);
|
|
case customComboBox: return new CustomToolbarComboBox (itemId);
|
|
default: break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private:
|
|
StringArray iconNames;
|
|
OwnedArray <Drawable> iconsFromZipFile;
|
|
|
|
// This is a little utility to create a button with one of the SVG images in
|
|
// our embedded ZIP file "icons.zip"
|
|
ToolbarButton* createButtonFromZipFileSVG (const int itemId, const String& text, const String& filename)
|
|
{
|
|
if (iconsFromZipFile.size() == 0)
|
|
{
|
|
// If we've not already done so, load all the images from the zip file..
|
|
MemoryInputStream iconsFileStream (BinaryData::icons_zip, BinaryData::icons_zipSize, false);
|
|
ZipFile icons (&iconsFileStream, false);
|
|
|
|
for (int i = 0; i < icons.getNumEntries(); ++i)
|
|
{
|
|
ScopedPointer<InputStream> svgFileStream (icons.createStreamForEntry (i));
|
|
|
|
if (svgFileStream != 0)
|
|
{
|
|
iconNames.add (icons.getEntry(i)->filename);
|
|
iconsFromZipFile.add (Drawable::createFromImageDataStream (*svgFileStream));
|
|
}
|
|
}
|
|
}
|
|
|
|
Drawable* image = iconsFromZipFile [iconNames.indexOf (filename)]->createCopy();
|
|
return new ToolbarButton (itemId, text, image, 0);
|
|
}
|
|
|
|
// Demonstrates how to put a custom component into a toolbar - this one contains
|
|
// a ComboBox.
|
|
class CustomToolbarComboBox : public ToolbarItemComponent
|
|
{
|
|
public:
|
|
CustomToolbarComboBox (const int toolbarItemId)
|
|
: ToolbarItemComponent (toolbarItemId, "Custom Toolbar Item", false),
|
|
comboBox ("demo toolbar combo box")
|
|
{
|
|
addAndMakeVisible (&comboBox);
|
|
|
|
for (int i = 1; i < 20; ++i)
|
|
comboBox.addItem ("Toolbar ComboBox item " + String (i), i);
|
|
|
|
comboBox.setSelectedId (1);
|
|
comboBox.setEditableText (true);
|
|
}
|
|
|
|
~CustomToolbarComboBox()
|
|
{
|
|
}
|
|
|
|
bool getToolbarItemSizes (int /*toolbarDepth*/, bool isToolbarVertical,
|
|
int& preferredSize, int& minSize, int& maxSize)
|
|
{
|
|
if (isToolbarVertical)
|
|
return false;
|
|
|
|
preferredSize = 250;
|
|
minSize = 80;
|
|
maxSize = 300;
|
|
return true;
|
|
}
|
|
|
|
void paintButtonArea (Graphics&, int, int, bool, bool)
|
|
{
|
|
}
|
|
|
|
void contentAreaChanged (const Rectangle<int>& contentArea)
|
|
{
|
|
comboBox.setSize (contentArea.getWidth() - 2,
|
|
jmin (contentArea.getHeight() - 2, 22));
|
|
|
|
comboBox.setCentrePosition (contentArea.getCentreX(), contentArea.getCentreY());
|
|
}
|
|
|
|
private:
|
|
ComboBox comboBox;
|
|
};
|
|
};
|
|
|
|
DemoToolbarItemFactory factory;
|
|
};
|
|
|
|
//==============================================================================
|
|
class DemoTabbedComponent : public TabbedComponent,
|
|
public ButtonListener
|
|
{
|
|
public:
|
|
DemoTabbedComponent()
|
|
: TabbedComponent (TabbedButtonBar::TabsAtTop)
|
|
{
|
|
addTab ("sliders", getRandomBrightColour(), createSlidersPage(), true);
|
|
addTab ("toolbars", getRandomBrightColour(), new ToolbarDemoComp(), true);
|
|
addTab ("buttons", getRandomBrightColour(), new ButtonsPage (this), true);
|
|
addTab ("radio buttons", getRandomBrightColour(), createRadioButtonPage(), true);
|
|
addTab ("misc widgets", getRandomBrightColour(), createMiscPage(), true);
|
|
}
|
|
|
|
~DemoTabbedComponent()
|
|
{
|
|
}
|
|
|
|
void buttonClicked (Button* button)
|
|
{
|
|
BubbleMessageComponent* bmc = new BubbleMessageComponent();
|
|
|
|
if (Desktop::canUseSemiTransparentWindows())
|
|
{
|
|
bmc->setAlwaysOnTop (true);
|
|
bmc->addToDesktop (0);
|
|
}
|
|
else
|
|
{
|
|
addChildComponent (bmc);
|
|
}
|
|
|
|
bmc->showAt (button, "This is a demo of the BubbleMessageComponent, which lets you pop up a message pointing at a component or somewhere on the screen.\n\nThe message bubbles will disappear after a timeout period, or when the mouse is clicked.",
|
|
2000, true, true);
|
|
}
|
|
|
|
static const Colour getRandomBrightColour()
|
|
{
|
|
return Colour (Random::getSystemRandom().nextFloat(), 0.1f, 0.97f, 1.0f);
|
|
}
|
|
};
|
|
|
|
|
|
//==============================================================================
|
|
class DemoBackgroundThread : public ThreadWithProgressWindow
|
|
{
|
|
public:
|
|
DemoBackgroundThread()
|
|
: ThreadWithProgressWindow ("busy doing some important things...",
|
|
true,
|
|
true)
|
|
{
|
|
setStatusMessage ("Getting ready...");
|
|
}
|
|
|
|
~DemoBackgroundThread()
|
|
{
|
|
}
|
|
|
|
void run()
|
|
{
|
|
setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar..
|
|
setStatusMessage ("Preparing to do some stuff...");
|
|
wait (2000);
|
|
|
|
const int thingsToDo = 10;
|
|
|
|
for (int i = 0; i < thingsToDo; ++i)
|
|
{
|
|
// must check this as often as possible, because this is
|
|
// how we know if the user's pressed 'cancel'
|
|
if (threadShouldExit())
|
|
return;
|
|
|
|
// this will update the progress bar on the dialog box
|
|
setProgress (i / (double) thingsToDo);
|
|
|
|
setStatusMessage (String (thingsToDo - i) + " things left to do...");
|
|
|
|
wait (500);
|
|
}
|
|
|
|
setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar..
|
|
setStatusMessage ("Finishing off the last few bits and pieces!");
|
|
wait (2000);
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
/** A DialogWindow containing a ColourSelector component */
|
|
class ColourSelectorDialogWindow : public DialogWindow
|
|
{
|
|
public:
|
|
ColourSelectorDialogWindow()
|
|
: DialogWindow ("Colour selector demo",
|
|
Colours::lightgrey,
|
|
true)
|
|
{
|
|
setContentComponent (new ColourSelector());
|
|
centreWithSize (400, 400);
|
|
setResizable (true, true);
|
|
}
|
|
|
|
~ColourSelectorDialogWindow()
|
|
{
|
|
}
|
|
|
|
void closeButtonPressed()
|
|
{
|
|
// we expect this component to be run within a modal loop, so when the close
|
|
// button is clicked, we can make it invisible to cause the loop to exit and the
|
|
// calling code will delete this object.
|
|
setVisible (false);
|
|
}
|
|
};
|
|
|
|
#if JUCE_MAC
|
|
|
|
//==============================================================================
|
|
/** This pops open a dialog box and waits for you to press keys on your Apple Remote,
|
|
which it describes in the box.
|
|
*/
|
|
class AppleRemoteTestWindow : public AlertWindow,
|
|
public AppleRemoteDevice
|
|
{
|
|
public:
|
|
AppleRemoteTestWindow()
|
|
: AlertWindow ("Apple Remote Control Test!",
|
|
"If you've got an Apple Remote, press some buttons now...",
|
|
AlertWindow::NoIcon)
|
|
{
|
|
addButton ("done", 0);
|
|
|
|
// (To open the device in non-exclusive mode, pass 'false' in here)..
|
|
if (! start (true))
|
|
setMessage ("Couldn't open the remote control device!");
|
|
}
|
|
|
|
~AppleRemoteTestWindow()
|
|
{
|
|
stop();
|
|
}
|
|
|
|
void buttonPressed (const ButtonType buttonId, const bool isDown)
|
|
{
|
|
String desc;
|
|
|
|
switch (buttonId)
|
|
{
|
|
case menuButton: desc = "menu button (short)"; break;
|
|
case playButton: desc = "play button"; break;
|
|
case plusButton: desc = "plus button"; break;
|
|
case minusButton: desc = "minus button"; break;
|
|
case rightButton: desc = "right button (short)"; break;
|
|
case leftButton: desc = "left button (short)"; break;
|
|
case rightButton_Long: desc = "right button (long)"; break;
|
|
case leftButton_Long: desc = "left button (long)"; break;
|
|
case menuButton_Long: desc = "menu button (long)"; break;
|
|
case playButtonSleepMode: desc = "play (sleep mode)"; break;
|
|
case switched: desc = "remote switched"; break;
|
|
}
|
|
|
|
if (isDown)
|
|
desc << " -- [down]";
|
|
else
|
|
desc << " -- [up]";
|
|
|
|
setMessage (desc);
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
//==============================================================================
|
|
class WidgetsDemo : public Component,
|
|
public ButtonListener,
|
|
public SliderListener
|
|
{
|
|
public:
|
|
//==============================================================================
|
|
WidgetsDemo()
|
|
: menuButton ("click for a popup menu..",
|
|
"click for a demo of the different types of item you can put into a popup menu..."),
|
|
enableButton ("enable/disable components")
|
|
{
|
|
setName ("Widgets");
|
|
|
|
addAndMakeVisible (&tabs);
|
|
|
|
//==============================================================================
|
|
addAndMakeVisible (&menuButton);
|
|
menuButton.setBounds (10, 10, 200, 24);
|
|
menuButton.addListener (this);
|
|
menuButton.setTriggeredOnMouseDown (true); // because this button pops up a menu, this lets us
|
|
// hold down the button and drag straight onto the menu
|
|
|
|
//==============================================================================
|
|
addAndMakeVisible (&enableButton);
|
|
enableButton.setBounds (230, 10, 180, 24);
|
|
enableButton.setTooltip ("Enables/disables all the components");
|
|
enableButton.setToggleState (true, false);
|
|
enableButton.addListener (this);
|
|
|
|
addAndMakeVisible (&transformSlider);
|
|
transformSlider.setSliderStyle (Slider::LinearBar);
|
|
transformSlider.setTextValueSuffix (" degrees rotation");
|
|
transformSlider.setRange (-180.0, 180.0, 0.1);
|
|
transformSlider.setBounds (440, 10, 180, 24);
|
|
transformSlider.setTooltip ("Applies a transform to the components");
|
|
transformSlider.addListener (this);
|
|
}
|
|
|
|
~WidgetsDemo()
|
|
{
|
|
}
|
|
|
|
void resized()
|
|
{
|
|
tabs.setBounds (10, 40, getWidth() - 20, getHeight() - 50);
|
|
}
|
|
|
|
//==============================================================================
|
|
void buttonClicked (Button* button)
|
|
{
|
|
if (button == &enableButton)
|
|
{
|
|
const bool enabled = enableButton.getToggleState();
|
|
|
|
menuButton.setEnabled (enabled);
|
|
tabs.setEnabled (enabled);
|
|
}
|
|
else if (button == &menuButton)
|
|
{
|
|
PopupMenu m;
|
|
m.addItem (1, "Normal item");
|
|
m.addItem (2, "Disabled item", false);
|
|
m.addItem (3, "Ticked item", true, true);
|
|
m.addColouredItem (4, "Coloured item", Colours::green);
|
|
m.addSeparator();
|
|
m.addCustomItem (5, new CustomMenuComponent());
|
|
|
|
m.addSeparator();
|
|
|
|
PopupMenu tabsMenu;
|
|
tabsMenu.addItem (1001, "Show tabs at the top", true, tabs.getOrientation() == TabbedButtonBar::TabsAtTop);
|
|
tabsMenu.addItem (1002, "Show tabs at the bottom", true, tabs.getOrientation() == TabbedButtonBar::TabsAtBottom);
|
|
tabsMenu.addItem (1003, "Show tabs at the left", true, tabs.getOrientation() == TabbedButtonBar::TabsAtLeft);
|
|
tabsMenu.addItem (1004, "Show tabs at the right", true, tabs.getOrientation() == TabbedButtonBar::TabsAtRight);
|
|
m.addSubMenu ("Tab position", tabsMenu);
|
|
|
|
m.addSeparator();
|
|
|
|
PopupMenu dialogMenu;
|
|
dialogMenu.addItem (100, "Show a plain alert-window...");
|
|
dialogMenu.addItem (101, "Show an alert-window with a 'warning' icon...");
|
|
dialogMenu.addItem (102, "Show an alert-window with an 'info' icon...");
|
|
dialogMenu.addItem (103, "Show an alert-window with a 'question' icon...");
|
|
|
|
dialogMenu.addSeparator();
|
|
|
|
dialogMenu.addItem (110, "Show an ok/cancel alert-window...");
|
|
|
|
dialogMenu.addSeparator();
|
|
|
|
dialogMenu.addItem (111, "Show an alert-window with some extra components...");
|
|
|
|
dialogMenu.addSeparator();
|
|
|
|
dialogMenu.addItem (112, "Show a ThreadWithProgressWindow demo...");
|
|
|
|
m.addSubMenu ("AlertWindow demonstrations", dialogMenu);
|
|
|
|
m.addSeparator();
|
|
|
|
m.addItem (120, "Show a colour selector demo...");
|
|
m.addSeparator();
|
|
|
|
#if JUCE_MAC
|
|
m.addItem (140, "Run the Apple Remote Control test...");
|
|
m.addSeparator();
|
|
#endif
|
|
|
|
PopupMenu nativeFileChoosers;
|
|
nativeFileChoosers.addItem (121, "'Load' file browser...");
|
|
nativeFileChoosers.addItem (124, "'Load' file browser with an image file preview...");
|
|
nativeFileChoosers.addItem (122, "'Save' file browser...");
|
|
nativeFileChoosers.addItem (123, "'Choose directory' file browser...");
|
|
|
|
PopupMenu juceFileChoosers;
|
|
juceFileChoosers.addItem (131, "'Load' file browser...");
|
|
juceFileChoosers.addItem (134, "'Load' file browser with an image file preview...");
|
|
juceFileChoosers.addItem (132, "'Save' file browser...");
|
|
juceFileChoosers.addItem (133, "'Choose directory' file browser...");
|
|
|
|
PopupMenu fileChoosers;
|
|
fileChoosers.addSubMenu ("Operating system dialogs", nativeFileChoosers);
|
|
fileChoosers.addSubMenu ("Juce dialogs", juceFileChoosers);
|
|
|
|
m.addSubMenu ("File chooser dialogs", fileChoosers);
|
|
|
|
int result = m.showAt (&menuButton);
|
|
|
|
if (result != 0)
|
|
{
|
|
// user chose something from the menu..
|
|
|
|
if (result >= 100 && result < 105)
|
|
{
|
|
AlertWindow::AlertIconType icon = AlertWindow::NoIcon;
|
|
|
|
if (result == 101)
|
|
icon = AlertWindow::WarningIcon;
|
|
else if (result == 102)
|
|
icon = AlertWindow::InfoIcon;
|
|
else if (result == 103)
|
|
icon = AlertWindow::QuestionIcon;
|
|
|
|
AlertWindow::showMessageBox (icon,
|
|
"This is an AlertWindow",
|
|
"And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.",
|
|
"ok");
|
|
}
|
|
else if (result == 110)
|
|
{
|
|
bool userPickedOk
|
|
= AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon,
|
|
"This is an ok/cancel AlertWindow",
|
|
"And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.");
|
|
|
|
(void) userPickedOk; // (just avoids a compiler warning about unused variables)
|
|
}
|
|
else if (result == 111)
|
|
{
|
|
AlertWindow w ("AlertWindow demo..",
|
|
"This AlertWindow has a couple of extra components added to show how to add drop-down lists and text entry boxes.",
|
|
AlertWindow::QuestionIcon);
|
|
|
|
w.addTextEditor ("text", "enter some text here", "text field:");
|
|
|
|
StringArray options;
|
|
options.add ("option 1");
|
|
options.add ("option 2");
|
|
options.add ("option 3");
|
|
options.add ("option 4");
|
|
w.addComboBox ("option", options, "some options");
|
|
|
|
w.addButton ("ok", 1, KeyPress (KeyPress::returnKey, 0, 0));
|
|
w.addButton ("cancel", 0, KeyPress (KeyPress::escapeKey, 0, 0));
|
|
|
|
if (w.runModalLoop() != 0) // is they picked 'ok'
|
|
{
|
|
// this is the item they chose in the drop-down list..
|
|
const int optionIndexChosen = w.getComboBoxComponent ("option")->getSelectedItemIndex();
|
|
(void) optionIndexChosen; // (just avoids a compiler warning about unused variables)
|
|
|
|
|
|
// this is the text they entered..
|
|
String text = w.getTextEditorContents ("text");
|
|
|
|
}
|
|
}
|
|
else if (result == 112)
|
|
{
|
|
DemoBackgroundThread demoThread;
|
|
|
|
if (demoThread.runThread())
|
|
{
|
|
// thread finished normally..
|
|
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
|
|
"Progress window",
|
|
"Thread finished ok!");
|
|
}
|
|
else
|
|
{
|
|
// user pressed the cancel button..
|
|
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
|
|
"Progress window",
|
|
"You pressed cancel!");
|
|
}
|
|
}
|
|
else if (result == 120)
|
|
{
|
|
ColourSelectorDialogWindow colourDialog;
|
|
|
|
// this will run an event loop until the dialog's closeButtonPressed()
|
|
// method causes the loop to exit.
|
|
colourDialog.runModalLoop();
|
|
}
|
|
else if (result == 140)
|
|
{
|
|
#if JUCE_MAC
|
|
AppleRemoteTestWindow test;
|
|
test.runModalLoop();
|
|
#endif
|
|
}
|
|
else if (result >= 121 && result < 139)
|
|
{
|
|
const bool useNativeVersion = result < 130;
|
|
if (result > 130)
|
|
result -= 10;
|
|
|
|
if (result == 121)
|
|
{
|
|
FileChooser fc ("Choose a file to open...",
|
|
File::getCurrentWorkingDirectory(),
|
|
"*",
|
|
useNativeVersion);
|
|
|
|
if (fc.browseForMultipleFilesToOpen())
|
|
{
|
|
String chosen;
|
|
for (int i = 0; i < fc.getResults().size(); ++i)
|
|
chosen << fc.getResults().getReference(i).getFullPathName() << "\n";
|
|
|
|
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
|
"File Chooser...",
|
|
"You picked: " + chosen);
|
|
}
|
|
}
|
|
else if (result == 124)
|
|
{
|
|
ImagePreviewComponent imagePreview;
|
|
imagePreview.setSize (200, 200);
|
|
|
|
FileChooser fc ("Choose an image to open...",
|
|
File::getCurrentWorkingDirectory(),
|
|
"*.jpg;*.jpeg;*.png;*.gif",
|
|
useNativeVersion);
|
|
|
|
if (fc.browseForMultipleFilesToOpen (&imagePreview))
|
|
{
|
|
String chosen;
|
|
for (int i = 0; i < fc.getResults().size(); ++i)
|
|
chosen << fc.getResults().getReference(i).getFullPathName() << "\n";
|
|
|
|
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
|
"File Chooser...",
|
|
"You picked: " + chosen);
|
|
}
|
|
}
|
|
else if (result == 122)
|
|
{
|
|
FileChooser fc ("Choose a file to save...",
|
|
File::getCurrentWorkingDirectory(),
|
|
"*",
|
|
useNativeVersion);
|
|
|
|
if (fc.browseForFileToSave (true))
|
|
{
|
|
File chosenFile = fc.getResult();
|
|
|
|
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
|
"File Chooser...",
|
|
"You picked: " + chosenFile.getFullPathName());
|
|
}
|
|
}
|
|
else if (result == 123)
|
|
{
|
|
FileChooser fc ("Choose a directory...",
|
|
File::getCurrentWorkingDirectory(),
|
|
"*",
|
|
useNativeVersion);
|
|
|
|
if (fc.browseForDirectory())
|
|
{
|
|
File chosenDirectory = fc.getResult();
|
|
|
|
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
|
"File Chooser...",
|
|
"You picked: " + chosenDirectory.getFullPathName());
|
|
}
|
|
}
|
|
}
|
|
else if (result == 1001)
|
|
{
|
|
tabs.setOrientation (TabbedButtonBar::TabsAtTop);
|
|
}
|
|
else if (result == 1002)
|
|
{
|
|
tabs.setOrientation (TabbedButtonBar::TabsAtBottom);
|
|
}
|
|
else if (result == 1003)
|
|
{
|
|
tabs.setOrientation (TabbedButtonBar::TabsAtLeft);
|
|
}
|
|
else if (result == 1004)
|
|
{
|
|
tabs.setOrientation (TabbedButtonBar::TabsAtRight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sliderValueChanged (Slider*)
|
|
{
|
|
// When you move the rotation slider, we'll apply a rotaion transform to the whole tabs component..
|
|
tabs.setTransform (AffineTransform::rotation ((float) (transformSlider.getValue() / (180.0 / double_Pi)),
|
|
getWidth() * 0.5f, getHeight() * 0.5f));
|
|
}
|
|
|
|
private:
|
|
TextButton menuButton;
|
|
ToggleButton enableButton;
|
|
Slider transformSlider;
|
|
DemoTabbedComponent tabs;
|
|
};
|
|
|
|
|
|
//==============================================================================
|
|
Component* createWidgetsDemo()
|
|
{
|
|
return new WidgetsDemo();
|
|
}
|