migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions
.clang-format.clang-tidy.editorconfig.gitattributes.gitignore.gitmodulesDockerfile.arch
Source
build_docker.sh
deps
clap-juce-extensions
.github
.gitignore.gitrepoCMakeLists.txtREADME.md
clap-libs
cmake
docs
examples
include
clap-juce-extensions
src
clap-juce-extensions_old
juce
.gitattributes
.github
.gitignore.gitrepoBREAKING-CHANGES.txtCMakeLists.txtChangeList.txtLICENSE.mdREADME.md
docs
examples
Assets
Audio
CMake
CMakeLists.txt
DSP
DemoRunner
Builds
CMakeLists.txtDemoRunner.jucer
JuceLibraryCode
Source
GUI
Plugins
Utilities
extras
AudioPerformanceTest
AudioPluginHost
AudioPluginHost.jucer
Builds
CMakeLists.txt
JuceLibraryCode
Source
BinaryBuilder
Build
CMakeLists.txt
NetworkGraphicsDemo
Projucer
Builds
CMakeLists.txt
JuceLibraryCode
Projucer.jucer
Source
Application
BinaryData
CodeEditor
ComponentEditor
Components
Documents
PaintElements
Properties
UI
jucer_BinaryResources.cppjucer_BinaryResources.hjucer_ComponentLayout.cppjucer_ComponentLayout.hjucer_GeneratedCode.cppjucer_GeneratedCode.hjucer_JucerDocument.cppjucer_JucerDocument.hjucer_ObjectTypes.cppjucer_ObjectTypes.hjucer_PaintRoutine.cppjucer_PaintRoutine.hjucer_UtilityFunctions.h
Licenses
LiveBuildEngine
Project
ProjectSaving
Settings
Utility
UnitTestRunner
WindowsDLL
modules
CMakeLists.txt
juce_analytics
juce_audio_basics
audio_play_head
buffers
juce_audio_basics.cppjuce_audio_basics.hjuce_audio_basics.mm
midi
mpe
native
sources
synthesisers
utilities
juce_audio_devices
juce_audio_formats
codecs
format
juce_audio_formats.cppjuce_audio_formats.hjuce_audio_formats.mm
sampler
juce_audio_plugin_client
AAX
ARA
AU
CMakeLists.txt
LV2
RTAS
Standalone
Unity
VST
VST3
juce_audio_plugin_client.hjuce_audio_plugin_client_AAX.cppjuce_audio_plugin_client_AAX.mmjuce_audio_plugin_client_ARA.cppjuce_audio_plugin_client_AU.rjuce_audio_plugin_client_AU_1.mmjuce_audio_plugin_client_AU_2.mmjuce_audio_plugin_client_AUv3.mmjuce_audio_plugin_client_LV2.cppjuce_audio_plugin_client_LV2.mmjuce_audio_plugin_client_RTAS.rjuce_audio_plugin_client_RTAS_utils.cppjuce_audio_plugin_client_RTAS_utils.mmjuce_audio_plugin_client_Standalone.cppjuce_audio_plugin_client_Unity.cppjuce_audio_plugin_client_VST2.cppjuce_audio_plugin_client_VST3.cppjuce_audio_plugin_client_VST_utils.mmjuce_audio_plugin_client_utils.cpp
utility
juce_audio_processors
format
format_types
LV2_SDK
README.mdgenerate_lv2_bundle_sources.pyjuce_lv2_config.h
lilv
lilv_config.h
lv2
serd
serd_config.h
sord
sord_config.h
sratom
VST3_SDK
pluginterfaces
juce_ARACommon.cppjuce_ARACommon.hjuce_ARAHosting.cppjuce_ARAHosting.hjuce_AU_Shared.hjuce_AudioUnitPluginFormat.hjuce_AudioUnitPluginFormat.mmjuce_LADSPAPluginFormat.cppjuce_LADSPAPluginFormat.hjuce_LV2Common.hjuce_LV2PluginFormat.cppjuce_LV2PluginFormat.hjuce_LV2PluginFormat_test.cppjuce_LV2Resources.hjuce_LV2SupportLibs.cppjuce_LegacyAudioParameter.cppjuce_VST3Common.hjuce_VST3Headers.hjuce_VST3PluginFormat.cppjuce_VST3PluginFormat.hjuce_VST3PluginFormat_test.cppjuce_VSTCommon.hjuce_VSTMidiEventList.hjuce_VSTPluginFormat.cppjuce_VSTPluginFormat.h
pslextensions
juce_audio_processors.cppjuce_audio_processors.hjuce_audio_processors.mmjuce_audio_processors_ara.cppjuce_audio_processors_lv2_libs.cpp
processors
scanning
utilities
juce_audio_utils
juce_box2d
box2d
juce_box2d.cppjuce_box2d.h
utils
juce_core
containers
files
javascript
juce_core.cppjuce_core.hjuce_core.mm
logging
maths
memory
misc
native
network
streams
system
text
threads
time
unit_tests
xml
zip
juce_cryptography
juce_data_structures
juce_dsp
containers
filter_design
frequency
juce_dsp.cppjuce_dsp.hjuce_dsp.mm
maths
native
processors
widgets
juce_events
juce_graphics
colour
contexts
effects
fonts
geometry
image_formats
images
juce_graphics.cppjuce_graphics.hjuce_graphics.mm
native
placement
juce_gui_basics
accessibility
application
buttons
commands
components
desktop
drawables
filebrowser
juce_gui_basics.cppjuce_gui_basics.hjuce_gui_basics.mm
keyboard
layout
lookandfeel
menus
misc
mouse
native
accessibility
java
javaopt
juce_MultiTouchMapper.hjuce_ScopedDPIAwarenessDisabler.hjuce_android_ContentSharer.cppjuce_android_FileChooser.cppjuce_android_Windowing.cppjuce_ios_ContentSharer.cppjuce_ios_FileChooser.mmjuce_ios_UIViewComponentPeer.mmjuce_ios_Windowing.mmjuce_linux_FileChooser.cppjuce_linux_Windowing.cppjuce_mac_CGMetalLayerRenderer.hjuce_mac_FileChooser.mmjuce_mac_MainMenu.mmjuce_mac_MouseCursor.mmjuce_mac_NSViewComponentPeer.mmjuce_mac_Windowing.mmjuce_win32_DragAndDrop.cppjuce_win32_FileChooser.cppjuce_win32_ScopedThreadDPIAwarenessSetter.hjuce_win32_Windowing.cpp
x11
positioning
properties
widgets
windows
juce_gui_extra
code_editor
documents
embedding
juce_gui_extra.cppjuce_gui_extra.hjuce_gui_extra.mm
misc
native
juce_opengl
juce_osc
juce_product_unlocking
juce_video
juce_old
linux

File diff suppressed because it is too large Load Diff

@ -1,477 +1,463 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that lets the user choose from a drop-down list of choices.
The combo-box has a list of text strings, each with an associated id number,
that will be shown in the drop-down list when the user clicks on the component.
The currently selected choice is displayed in the combo-box, and this can
either be read-only text, or editable.
To find out when the user selects a different item or edits the text, you
can assign a lambda to the onChange member, or register a ComboBox::Listener
to receive callbacks.
@tags{GUI}
*/
class JUCE_API ComboBox : public Component,
public SettableTooltipClient,
public Value::Listener,
private AsyncUpdater
{
public:
//==============================================================================
/** Creates a combo-box.
On construction, the text field will be empty, so you should call the
setSelectedId() or setText() method to choose the initial value before
displaying it.
@param componentName the name to set for the component (see Component::setName())
*/
explicit ComboBox (const String& componentName = {});
/** Destructor. */
~ComboBox() override;
//==============================================================================
/** Sets whether the text in the combo-box is editable.
The default state for a new ComboBox is non-editable, and can only be changed
by choosing from the drop-down list.
*/
void setEditableText (bool isEditable);
/** Returns true if the text is directly editable.
@see setEditableText
*/
bool isTextEditable() const noexcept;
/** Sets the style of justification to be used for positioning the text.
The default is Justification::centredLeft. The text is displayed using a
Label component inside the ComboBox.
*/
void setJustificationType (Justification justification);
/** Returns the current justification for the text box.
@see setJustificationType
*/
Justification getJustificationType() const noexcept;
//==============================================================================
/** Adds an item to be shown in the drop-down list.
@param newItemText the text of the item to show in the list
@param newItemId an associated ID number that can be set or retrieved - see
getSelectedId() and setSelectedId(). Note that this value can not
be 0!
@see setItemEnabled, addSeparator, addSectionHeading, getNumItems, getItemText, getItemId
*/
void addItem (const String& newItemText, int newItemId);
/** Adds an item to be shown in the drop-down list.
@param newItemText the text of the item to show in the list
@param newItemId an associated ID number that can be set or retrieved - see
getSelectedId() and setSelectedId(). Note that this value can not
be 0!
@param newItemImage an icon image that is shown to the left of text
@see setItemEnabled, addSeparator, addSectionHeading, getNumItems, getItemText, getItemId
*/
void addItem (const String& newItemText, int newItemId, const Image & newItemImage);
/** Adds an array of items to the drop-down list.
The item ID of each item will be its index in the StringArray + firstItemIdOffset.
*/
void addItemList (const StringArray& items, int firstItemIdOffset);
/** Adds a separator line to the drop-down list.
This is like adding a separator to a popup menu. See PopupMenu::addSeparator().
*/
void addSeparator();
/** Adds a heading to the drop-down list, so that you can group the items into
different sections.
The headings are indented slightly differently to set them apart from the
items on the list, and obviously can't be selected. You might want to add
separators between your sections too.
@see addItem, addSeparator
*/
void addSectionHeading (const String& headingName);
/** This allows items in the drop-down list to be selectively disabled.
When you add an item, it's enabled by default, but you can call this
method to change its status.
If you disable an item which is already selected, this won't change the
current selection - it just stops the user choosing that item from the list.
*/
void setItemEnabled (int itemId, bool shouldBeEnabled);
/** Returns true if the given item is enabled. */
bool isItemEnabled (int itemId) const noexcept;
/** Changes the text for an existing item.
*/
void changeItemText (int itemId, const String& newText);
/** Removes all the items from the drop-down list.
If this call causes the content to be cleared, and a change-message
will be broadcast according to the notification parameter.
@see addItem, getNumItems
*/
void clear (NotificationType notification = sendNotificationAsync);
/** Returns the number of items that have been added to the list.
Note that this doesn't include headers or separators.
*/
int getNumItems() const noexcept;
/** Returns the text for one of the items in the list.
Note that this doesn't include headers or separators.
@param index the item's index from 0 to (getNumItems() - 1)
*/
String getItemText (int index) const;
/** Returns the ID for one of the items in the list.
Note that this doesn't include headers or separators.
@param index the item's index from 0 to (getNumItems() - 1)
*/
int getItemId (int index) const noexcept;
/** Returns the index in the list of a particular item ID.
If no such ID is found, this will return -1.
*/
int indexOfItemId (int itemId) const noexcept;
//==============================================================================
/** Returns the ID of the item that's currently shown in the box.
If no item is selected, or if the text is editable and the user
has entered something which isn't one of the items in the list, then
this will return 0.
@see setSelectedId, getSelectedItemIndex, getText
*/
int getSelectedId() const noexcept;
/** Returns a Value object that can be used to get or set the selected item's ID.
You can call Value::referTo() on this object to make the combo box control
another Value object.
*/
Value& getSelectedIdAsValue() { return currentId; }
/** Sets one of the items to be the current selection.
This will set the ComboBox's text to that of the item that matches
this ID.
@param newItemId the new item to select
@param notification determines the type of change notification that will
be sent to listeners if the value changes
@see getSelectedId, setSelectedItemIndex, setText
*/
void setSelectedId (int newItemId,
NotificationType notification = sendNotificationAsync);
//==============================================================================
/** Returns the index of the item that's currently shown in the box.
If no item is selected, or if the text is editable and the user
has entered something which isn't one of the items in the list, then
this will return -1.
@see setSelectedItemIndex, getSelectedId, getText
*/
int getSelectedItemIndex() const;
/** Sets one of the items to be the current selection.
This will set the ComboBox's text to that of the item at the given
index in the list.
@param newItemIndex the new item to select
@param notification determines the type of change notification that will
be sent to listeners if the value changes
@see getSelectedItemIndex, setSelectedId, setText
*/
void setSelectedItemIndex (int newItemIndex,
NotificationType notification = sendNotificationAsync);
//==============================================================================
/** Returns the text that is currently shown in the combo-box's text field.
If the ComboBox has editable text, then this text may have been edited
by the user; otherwise it will be one of the items from the list, or
possibly an empty string if nothing was selected.
@see setText, getSelectedId, getSelectedItemIndex
*/
String getText() const;
/** Sets the contents of the combo-box's text field.
The text passed-in will be set as the current text regardless of whether
it is one of the items in the list. If the current text isn't one of the
items, then getSelectedId() will return 0, otherwise it will return
the appropriate ID.
@param newText the text to select
@param notification determines the type of change notification that will
be sent to listeners if the text changes
@see getText
*/
void setText (const String& newText,
NotificationType notification = sendNotificationAsync);
/** Programmatically opens the text editor to allow the user to edit the current item.
This is the same effect as when the box is clicked-on.
@see Label::showEditor();
*/
void showEditor();
/** Pops up the combo box's list.
This is virtual so that you can override it with your own custom popup
mechanism if you need some really unusual behaviour.
*/
virtual void showPopup();
/** Hides the combo box's popup list, if it's currently visible. */
void hidePopup();
/** Returns true if the popup menu is currently being shown. */
bool isPopupActive() const noexcept { return menuActive; }
/** Returns the PopupMenu object associated with the ComboBox.
Can be useful for adding sub-menus to the ComboBox standard PopupMenu
*/
PopupMenu* getRootMenu() noexcept { return &currentMenu; }
/** Returns the PopupMenu object associated with the ComboBox. */
const PopupMenu* getRootMenu() const noexcept { return &currentMenu; }
//==============================================================================
/**
A class for receiving events from a ComboBox.
You can register a ComboBox::Listener with a ComboBox using the ComboBox::addListener()
method, and it will be called when the selected item in the box changes.
@see ComboBox::addListener, ComboBox::removeListener
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Called when a ComboBox has its selected item changed. */
virtual void comboBoxChanged (ComboBox* comboBoxThatHasChanged) = 0;
};
/** Registers a listener that will be called when the box's content changes. */
void addListener (Listener* listener);
/** Deregisters a previously-registered listener. */
void removeListener (Listener* listener);
//==============================================================================
/** You can assign a lambda to this callback object to have it called when the selected ID is changed. */
std::function<void()> onChange;
//==============================================================================
/** Sets a message to display when there is no item currently selected.
@see getTextWhenNothingSelected
*/
void setTextWhenNothingSelected (const String& newMessage);
/** Returns the text that is shown when no item is selected.
@see setTextWhenNothingSelected
*/
String getTextWhenNothingSelected() const;
/** Sets the message to show when there are no items in the list, and the user clicks
on the drop-down box.
By default it just says "no choices", but this lets you change it to something more
meaningful.
*/
void setTextWhenNoChoicesAvailable (const String& newMessage);
/** Returns the text shown when no items have been added to the list.
@see setTextWhenNoChoicesAvailable
*/
String getTextWhenNoChoicesAvailable() const;
//==============================================================================
/** Gives the ComboBox a tooltip. */
void setTooltip (const String& newTooltip) override;
/** This can be used to allow the scroll-wheel to nudge the chosen item.
By default it's disabled, and I'd recommend leaving it disabled if there's any
chance that the control might be inside a scrollable list or viewport.
*/
void setScrollWheelEnabled (bool enabled) noexcept;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the combo box.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
To change the colours of the menu that pops up, you can set the colour IDs in PopupMenu::ColourIDs.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1000b00, /**< The background colour to fill the box with. */
textColourId = 0x1000a00, /**< The colour for the text in the box. */
outlineColourId = 0x1000c00, /**< The colour for an outline around the box. */
buttonColourId = 0x1000d00, /**< The base colour for the button (a LookAndFeel class will probably use variations on this). */
arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */
focusedOutlineColourId = 0x1000f00 /**< The colour that will be used to draw a box around the edge of the component when it has focus. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes to provide
ComboBox functionality.
*/
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawComboBox (Graphics&, int width, int height, bool isButtonDown,
int buttonX, int buttonY, int buttonW, int buttonH,
ComboBox&) = 0;
virtual Font getComboBoxFont (ComboBox&) = 0;
virtual Label* createComboBoxTextBox (ComboBox&) = 0;
virtual void positionComboBoxText (ComboBox&, Label& labelToPosition, Drawable * image = nullptr) = 0;
virtual PopupMenu::Options getOptionsForComboBoxPopupMenu (ComboBox&, Label&) = 0;
virtual void drawComboBoxTextWhenNothingSelected (Graphics&, ComboBox&, Label&) = 0;
};
//==============================================================================
/** @internal */
void enablementChanged() override;
/** @internal */
void colourChanged() override;
/** @internal */
void focusGained (Component::FocusChangeType) override;
/** @internal */
void focusLost (Component::FocusChangeType) override;
/** @internal */
void handleAsyncUpdate() override;
/** @internal */
String getTooltip() override { return label->getTooltip(); }
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
void mouseDrag (const MouseEvent&) override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
bool keyStateChanged (bool) override;
/** @internal */
bool keyPressed (const KeyPress&) override;
/** @internal */
void valueChanged (Value&) override;
/** @internal */
void parentHierarchyChanged() override;
//==============================================================================
#ifndef DOXYGEN
// These methods' bool parameters have changed: see their new method signatures.
[[deprecated]] void clear (bool);
[[deprecated]] void setSelectedId (int, bool);
[[deprecated]] void setSelectedItemIndex (int, bool);
[[deprecated]] void setText (const String&, bool);
#endif
private:
//==============================================================================
enum EditableState
{
editableUnknown,
labelIsNotEditable,
labelIsEditable
};
PopupMenu currentMenu;
Value currentId;
int lastCurrentId = 0;
bool isButtonDown = false, menuActive = false, scrollWheelEnabled = false;
float mouseWheelAccumulator = 0;
ListenerList<Listener> listeners;
std::unique_ptr<Label> label;
String textWhenNothingSelected, noChoicesMessage;
EditableState labelEditableState = editableUnknown;
std::unique_ptr<Drawable> image;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
PopupMenu::Item* getItemForId (int) const noexcept;
PopupMenu::Item* getItemForIndex (int) const noexcept;
bool selectIfEnabled (int index);
bool nudgeSelectedItem (int delta);
void sendChange (NotificationType);
void showPopupIfNotActive();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBox)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that lets the user choose from a drop-down list of choices.
The combo-box has a list of text strings, each with an associated id number,
that will be shown in the drop-down list when the user clicks on the component.
The currently selected choice is displayed in the combo-box, and this can
either be read-only text, or editable.
To find out when the user selects a different item or edits the text, you
can assign a lambda to the onChange member, or register a ComboBox::Listener
to receive callbacks.
@tags{GUI}
*/
class JUCE_API ComboBox : public Component,
public SettableTooltipClient,
public Value::Listener,
private AsyncUpdater
{
public:
//==============================================================================
/** Creates a combo-box.
On construction, the text field will be empty, so you should call the
setSelectedId() or setText() method to choose the initial value before
displaying it.
@param componentName the name to set for the component (see Component::setName())
*/
explicit ComboBox (const String& componentName = {});
/** Destructor. */
~ComboBox() override;
//==============================================================================
/** Sets whether the text in the combo-box is editable.
The default state for a new ComboBox is non-editable, and can only be changed
by choosing from the drop-down list.
*/
void setEditableText (bool isEditable);
/** Returns true if the text is directly editable.
@see setEditableText
*/
bool isTextEditable() const noexcept;
/** Sets the style of justification to be used for positioning the text.
The default is Justification::centredLeft. The text is displayed using a
Label component inside the ComboBox.
*/
void setJustificationType (Justification justification);
/** Returns the current justification for the text box.
@see setJustificationType
*/
Justification getJustificationType() const noexcept;
//==============================================================================
/** Adds an item to be shown in the drop-down list.
@param newItemText the text of the item to show in the list
@param newItemId an associated ID number that can be set or retrieved - see
getSelectedId() and setSelectedId(). Note that this value can not
be 0!
@see setItemEnabled, addSeparator, addSectionHeading, getNumItems, getItemText, getItemId
*/
void addItem (const String& newItemText, int newItemId);
/** Adds an array of items to the drop-down list.
The item ID of each item will be its index in the StringArray + firstItemIdOffset.
*/
void addItemList (const StringArray& items, int firstItemIdOffset);
/** Adds a separator line to the drop-down list.
This is like adding a separator to a popup menu. See PopupMenu::addSeparator().
*/
void addSeparator();
/** Adds a heading to the drop-down list, so that you can group the items into
different sections.
The headings are indented slightly differently to set them apart from the
items on the list, and obviously can't be selected. You might want to add
separators between your sections too.
@see addItem, addSeparator
*/
void addSectionHeading (const String& headingName);
/** This allows items in the drop-down list to be selectively disabled.
When you add an item, it's enabled by default, but you can call this
method to change its status.
If you disable an item which is already selected, this won't change the
current selection - it just stops the user choosing that item from the list.
*/
void setItemEnabled (int itemId, bool shouldBeEnabled);
/** Returns true if the given item is enabled. */
bool isItemEnabled (int itemId) const noexcept;
/** Changes the text for an existing item.
*/
void changeItemText (int itemId, const String& newText);
/** Removes all the items from the drop-down list.
If this call causes the content to be cleared, and a change-message
will be broadcast according to the notification parameter.
@see addItem, getNumItems
*/
void clear (NotificationType notification = sendNotificationAsync);
/** Returns the number of items that have been added to the list.
Note that this doesn't include headers or separators.
*/
int getNumItems() const noexcept;
/** Returns the text for one of the items in the list.
Note that this doesn't include headers or separators.
@param index the item's index from 0 to (getNumItems() - 1)
*/
String getItemText (int index) const;
/** Returns the ID for one of the items in the list.
Note that this doesn't include headers or separators.
@param index the item's index from 0 to (getNumItems() - 1)
*/
int getItemId (int index) const noexcept;
/** Returns the index in the list of a particular item ID.
If no such ID is found, this will return -1.
*/
int indexOfItemId (int itemId) const noexcept;
//==============================================================================
/** Returns the ID of the item that's currently shown in the box.
If no item is selected, or if the text is editable and the user
has entered something which isn't one of the items in the list, then
this will return 0.
@see setSelectedId, getSelectedItemIndex, getText
*/
int getSelectedId() const noexcept;
/** Returns a Value object that can be used to get or set the selected item's ID.
You can call Value::referTo() on this object to make the combo box control
another Value object.
*/
Value& getSelectedIdAsValue() { return currentId; }
/** Sets one of the items to be the current selection.
This will set the ComboBox's text to that of the item that matches
this ID.
@param newItemId the new item to select
@param notification determines the type of change notification that will
be sent to listeners if the value changes
@see getSelectedId, setSelectedItemIndex, setText
*/
void setSelectedId (int newItemId,
NotificationType notification = sendNotificationAsync);
//==============================================================================
/** Returns the index of the item that's currently shown in the box.
If no item is selected, or if the text is editable and the user
has entered something which isn't one of the items in the list, then
this will return -1.
@see setSelectedItemIndex, getSelectedId, getText
*/
int getSelectedItemIndex() const;
/** Sets one of the items to be the current selection.
This will set the ComboBox's text to that of the item at the given
index in the list.
@param newItemIndex the new item to select
@param notification determines the type of change notification that will
be sent to listeners if the value changes
@see getSelectedItemIndex, setSelectedId, setText
*/
void setSelectedItemIndex (int newItemIndex,
NotificationType notification = sendNotificationAsync);
//==============================================================================
/** Returns the text that is currently shown in the combo-box's text field.
If the ComboBox has editable text, then this text may have been edited
by the user; otherwise it will be one of the items from the list, or
possibly an empty string if nothing was selected.
@see setText, getSelectedId, getSelectedItemIndex
*/
String getText() const;
/** Sets the contents of the combo-box's text field.
The text passed-in will be set as the current text regardless of whether
it is one of the items in the list. If the current text isn't one of the
items, then getSelectedId() will return 0, otherwise it will return
the appropriate ID.
@param newText the text to select
@param notification determines the type of change notification that will
be sent to listeners if the text changes
@see getText
*/
void setText (const String& newText,
NotificationType notification = sendNotificationAsync);
/** Programmatically opens the text editor to allow the user to edit the current item.
This is the same effect as when the box is clicked-on.
@see Label::showEditor();
*/
void showEditor();
/** Pops up the combo box's list.
This is virtual so that you can override it with your own custom popup
mechanism if you need some really unusual behaviour.
*/
virtual void showPopup();
/** Hides the combo box's popup list, if it's currently visible. */
void hidePopup();
/** Returns true if the popup menu is currently being shown. */
bool isPopupActive() const noexcept { return menuActive; }
/** Returns the PopupMenu object associated with the ComboBox.
Can be useful for adding sub-menus to the ComboBox standard PopupMenu
*/
PopupMenu* getRootMenu() noexcept { return &currentMenu; }
/** Returns the PopupMenu object associated with the ComboBox. */
const PopupMenu* getRootMenu() const noexcept { return &currentMenu; }
//==============================================================================
/**
A class for receiving events from a ComboBox.
You can register a ComboBox::Listener with a ComboBox using the ComboBox::addListener()
method, and it will be called when the selected item in the box changes.
@see ComboBox::addListener, ComboBox::removeListener
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Called when a ComboBox has its selected item changed. */
virtual void comboBoxChanged (ComboBox* comboBoxThatHasChanged) = 0;
};
/** Registers a listener that will be called when the box's content changes. */
void addListener (Listener* listener);
/** Deregisters a previously-registered listener. */
void removeListener (Listener* listener);
//==============================================================================
/** You can assign a lambda to this callback object to have it called when the selected ID is changed. */
std::function<void()> onChange;
//==============================================================================
/** Sets a message to display when there is no item currently selected.
@see getTextWhenNothingSelected
*/
void setTextWhenNothingSelected (const String& newMessage);
/** Returns the text that is shown when no item is selected.
@see setTextWhenNothingSelected
*/
String getTextWhenNothingSelected() const;
/** Sets the message to show when there are no items in the list, and the user clicks
on the drop-down box.
By default it just says "no choices", but this lets you change it to something more
meaningful.
*/
void setTextWhenNoChoicesAvailable (const String& newMessage);
/** Returns the text shown when no items have been added to the list.
@see setTextWhenNoChoicesAvailable
*/
String getTextWhenNoChoicesAvailable() const;
//==============================================================================
/** Gives the ComboBox a tooltip. */
void setTooltip (const String& newTooltip) override;
/** This can be used to allow the scroll-wheel to nudge the chosen item.
By default it's disabled, and I'd recommend leaving it disabled if there's any
chance that the control might be inside a scrollable list or viewport.
*/
void setScrollWheelEnabled (bool enabled) noexcept;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the combo box.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
To change the colours of the menu that pops up, you can set the colour IDs in PopupMenu::ColourIDs.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1000b00, /**< The background colour to fill the box with. */
textColourId = 0x1000a00, /**< The colour for the text in the box. */
outlineColourId = 0x1000c00, /**< The colour for an outline around the box. */
buttonColourId = 0x1000d00, /**< The base colour for the button (a LookAndFeel class will probably use variations on this). */
arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */
focusedOutlineColourId = 0x1000f00 /**< The colour that will be used to draw a box around the edge of the component when it has focus. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes to provide
ComboBox functionality.
*/
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawComboBox (Graphics&, int width, int height, bool isButtonDown,
int buttonX, int buttonY, int buttonW, int buttonH,
ComboBox&) = 0;
virtual Font getComboBoxFont (ComboBox&) = 0;
virtual Label* createComboBoxTextBox (ComboBox&) = 0;
virtual void positionComboBoxText (ComboBox&, Label& labelToPosition) = 0;
virtual PopupMenu::Options getOptionsForComboBoxPopupMenu (ComboBox&, Label&) = 0;
virtual void drawComboBoxTextWhenNothingSelected (Graphics&, ComboBox&, Label&) = 0;
};
//==============================================================================
/** @internal */
void enablementChanged() override;
/** @internal */
void colourChanged() override;
/** @internal */
void focusGained (Component::FocusChangeType) override;
/** @internal */
void focusLost (Component::FocusChangeType) override;
/** @internal */
void handleAsyncUpdate() override;
/** @internal */
String getTooltip() override { return label->getTooltip(); }
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
void mouseDrag (const MouseEvent&) override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
bool keyStateChanged (bool) override;
/** @internal */
bool keyPressed (const KeyPress&) override;
/** @internal */
void valueChanged (Value&) override;
/** @internal */
void parentHierarchyChanged() override;
//==============================================================================
#ifndef DOXYGEN
// These methods' bool parameters have changed: see their new method signatures.
[[deprecated]] void clear (bool);
[[deprecated]] void setSelectedId (int, bool);
[[deprecated]] void setSelectedItemIndex (int, bool);
[[deprecated]] void setText (const String&, bool);
#endif
private:
//==============================================================================
enum EditableState
{
editableUnknown,
labelIsNotEditable,
labelIsEditable
};
PopupMenu currentMenu;
Value currentId;
int lastCurrentId = 0;
bool isButtonDown = false, menuActive = false, scrollWheelEnabled = false;
float mouseWheelAccumulator = 0;
ListenerList<Listener> listeners;
std::unique_ptr<Label> label;
String textWhenNothingSelected, noChoicesMessage;
EditableState labelEditableState = editableUnknown;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
PopupMenu::Item* getItemForId (int) const noexcept;
PopupMenu::Item* getItemForIndex (int) const noexcept;
bool selectIfEnabled (int index);
bool nudgeSelectedItem (int delta);
void sendChange (NotificationType);
void showPopupIfNotActive();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBox)
};
} // namespace juce

@ -1,107 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ImageComponent::ImageComponent (const String& name)
: Component (name),
placement (RectanglePlacement::centred)
{
}
ImageComponent::~ImageComponent()
{
}
void ImageComponent::setImage (const Image& newImage)
{
if (image != newImage)
{
image = newImage;
repaint();
}
}
void ImageComponent::setImage (const Image& newImage, RectanglePlacement placementToUse)
{
if (image != newImage || placement != placementToUse)
{
image = newImage;
placement = placementToUse;
repaint();
}
}
void ImageComponent::setImagePlacement (RectanglePlacement newPlacement)
{
if (placement != newPlacement)
{
placement = newPlacement;
repaint();
}
}
const Image& ImageComponent::getImage() const
{
return image;
}
RectanglePlacement ImageComponent::getImagePlacement() const
{
return placement;
}
void ImageComponent::paint (Graphics& g)
{
g.setOpacity (1.0f);
g.drawImage (image, getLocalBounds().toFloat(), placement);
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ImageComponent::createAccessibilityHandler()
{
class ImageComponentAccessibilityHandler : public AccessibilityHandler
{
public:
explicit ImageComponentAccessibilityHandler (ImageComponent& imageComponentToWrap)
: AccessibilityHandler (imageComponentToWrap, AccessibilityRole::image),
imageComponent (imageComponentToWrap)
{
}
String getHelp() const override { return imageComponent.getTooltip(); }
private:
ImageComponent& imageComponent;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageComponentAccessibilityHandler)
};
return std::make_unique<ImageComponentAccessibilityHandler> (*this);
}
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ImageComponent::ImageComponent (const String& name)
: Component (name),
placement (RectanglePlacement::centred)
{
}
ImageComponent::~ImageComponent()
{
}
void ImageComponent::setImage (const Image& newImage)
{
if (image != newImage)
{
image = newImage;
repaint();
}
}
void ImageComponent::setImage (const Image& newImage, RectanglePlacement placementToUse)
{
if (image != newImage || placement != placementToUse)
{
image = newImage;
placement = placementToUse;
repaint();
}
}
void ImageComponent::setImagePlacement (RectanglePlacement newPlacement)
{
if (placement != newPlacement)
{
placement = newPlacement;
repaint();
}
}
const Image& ImageComponent::getImage() const
{
return image;
}
RectanglePlacement ImageComponent::getImagePlacement() const
{
return placement;
}
void ImageComponent::paint (Graphics& g)
{
g.setOpacity (1.0f);
g.drawImage (image, getLocalBounds().toFloat(), placement);
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ImageComponent::createAccessibilityHandler()
{
class ImageComponentAccessibilityHandler : public AccessibilityHandler
{
public:
explicit ImageComponentAccessibilityHandler (ImageComponent& imageComponentToWrap)
: AccessibilityHandler (imageComponentToWrap, AccessibilityRole::image),
imageComponent (imageComponentToWrap)
{
}
String getHelp() const override { return imageComponent.getTooltip(); }
private:
ImageComponent& imageComponent;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageComponentAccessibilityHandler)
};
return std::make_unique<ImageComponentAccessibilityHandler> (*this);
}
} // namespace juce

@ -1,81 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that simply displays an image.
Use setImage to give it an image, and it'll display it - simple as that!
@tags{GUI}
*/
class JUCE_API ImageComponent : public Component,
public SettableTooltipClient
{
public:
//==============================================================================
/** Creates an ImageComponent. */
ImageComponent (const String& componentName = String());
/** Destructor. */
~ImageComponent() override;
//==============================================================================
/** Sets the image that should be displayed. */
void setImage (const Image& newImage);
/** Sets the image that should be displayed, and its placement within the component. */
void setImage (const Image& newImage,
RectanglePlacement placementToUse);
/** Returns the current image. */
const Image& getImage() const;
/** Sets the method of positioning that will be used to fit the image within the component's bounds.
By default the positioning is centred, and will fit the image inside the component's bounds
whilst keeping its aspect ratio correct, but you can change it to whatever layout you need.
*/
void setImagePlacement (RectanglePlacement newPlacement);
/** Returns the current image placement. */
RectanglePlacement getImagePlacement() const;
//==============================================================================
/** @internal */
void paint (Graphics&) override;
private:
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
Image image;
RectanglePlacement placement;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageComponent)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that simply displays an image.
Use setImage to give it an image, and it'll display it - simple as that!
@tags{GUI}
*/
class JUCE_API ImageComponent : public Component,
public SettableTooltipClient
{
public:
//==============================================================================
/** Creates an ImageComponent. */
ImageComponent (const String& componentName = String());
/** Destructor. */
~ImageComponent() override;
//==============================================================================
/** Sets the image that should be displayed. */
void setImage (const Image& newImage);
/** Sets the image that should be displayed, and its placement within the component. */
void setImage (const Image& newImage,
RectanglePlacement placementToUse);
/** Returns the current image. */
const Image& getImage() const;
/** Sets the method of positioning that will be used to fit the image within the component's bounds.
By default the positioning is centred, and will fit the image inside the component's bounds
whilst keeping its aspect ratio correct, but you can change it to whatever layout you need.
*/
void setImagePlacement (RectanglePlacement newPlacement);
/** Returns the current image placement. */
RectanglePlacement getImagePlacement() const;
//==============================================================================
/** @internal */
void paint (Graphics&) override;
private:
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
Image image;
RectanglePlacement placement;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageComponent)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

@ -1,366 +1,366 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that displays a text string, and can optionally become a text
editor when clicked.
@tags{GUI}
*/
class JUCE_API Label : public Component,
public SettableTooltipClient,
protected TextEditor::Listener,
private ComponentListener,
private Value::Listener
{
public:
//==============================================================================
/** Creates a Label.
@param componentName the name to give the component
@param labelText the text to show in the label
*/
Label (const String& componentName = String(),
const String& labelText = String());
/** Destructor. */
~Label() override;
//==============================================================================
/** Changes the label text.
The NotificationType parameter indicates whether to send a change message to
any Label::Listener objects if the new text is different.
*/
void setText (const String& newText,
NotificationType notification);
/** Returns the label's current text.
@param returnActiveEditorContents if this is true and the label is currently
being edited, then this method will return the
text as it's being shown in the editor. If false,
then the value returned here won't be updated until
the user has finished typing and pressed the return
key.
*/
String getText (bool returnActiveEditorContents = false) const;
/** Returns the text content as a Value object.
You can call Value::referTo() on this object to make the label read and control
a Value object that you supply.
*/
Value& getTextValue() noexcept { return textValue; }
//==============================================================================
/** Changes the font to use to draw the text.
@see getFont
*/
void setFont (const Font& newFont);
/** Returns the font currently being used.
This may be the one set by setFont(), unless it has been overridden by the current LookAndFeel
@see setFont
*/
Font getFont() const noexcept;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the label.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
Note that you can also use the constants from TextEditor::ColourIds to change the
colour of the text editor that is opened when a label is editable.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */
textColourId = 0x1000281, /**< The colour for the text. */
outlineColourId = 0x1000282, /**< An optional colour to use to draw a border around the label.
Leave this transparent to not have an outline. */
backgroundWhenEditingColourId = 0x1000283, /**< The background colour when the label is being edited. */
textWhenEditingColourId = 0x1000284, /**< The colour for the text when the label is being edited. */
outlineWhenEditingColourId = 0x1000285 /**< An optional border colour when the label is being edited. */
};
//==============================================================================
/** Sets the style of justification to be used for positioning the text.
(The default is Justification::centredLeft)
*/
void setJustificationType (Justification justification);
/** Returns the type of justification, as set in setJustificationType(). */
Justification getJustificationType() const noexcept { return justification; }
/** Changes the border that is left between the edge of the component and the text.
By default there's a small gap left at the sides of the component to allow for
the drawing of the border, but you can change this if necessary.
*/
void setBorderSize (BorderSize<int> newBorderSize);
/** Returns the size of the border to be left around the text. */
BorderSize<int> getBorderSize() const noexcept { return border; }
/** Makes this label "stick to" another component.
This will cause the label to follow another component around, staying
either to its left or above it.
@param owner the component to follow
@param onLeft if true, the label will stay on the left of its component; if
false, it will stay above it.
*/
void attachToComponent (Component* owner, bool onLeft);
/** If this label has been attached to another component using attachToComponent, this
returns the other component.
Returns nullptr if the label is not attached.
*/
Component* getAttachedComponent() const;
/** If the label is attached to the left of another component, this returns true.
Returns false if the label is above the other component. This is only relevant if
attachToComponent() has been called.
*/
bool isAttachedOnLeft() const noexcept { return leftOfOwnerComp; }
/** Specifies the minimum amount that the font can be squashed horizontally before it starts
using ellipsis. Use a value of 0 for a default value.
@see Graphics::drawFittedText
*/
void setMinimumHorizontalScale (float newScale);
/** Specifies the amount that the font can be squashed horizontally. */
float getMinimumHorizontalScale() const noexcept { return minimumHorizontalScale; }
/** Set a keyboard type for use when the text editor is shown. */
void setKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept { keyboardType = type; }
//==============================================================================
/**
A class for receiving events from a Label.
You can register a Label::Listener with a Label using the Label::addListener()
method, and it will be called when the text of the label changes, either because
of a call to Label::setText() or by the user editing the text (if the label is
editable).
@see Label::addListener, Label::removeListener
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Called when a Label's text has changed. */
virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
/** Called when a Label goes into editing mode and displays a TextEditor. */
virtual void editorShown (Label*, TextEditor&) {}
/** Called when a Label is about to delete its TextEditor and exit editing mode. */
virtual void editorHidden (Label*, TextEditor&) {}
};
/** Registers a listener that will be called when the label's text changes. */
void addListener (Listener* listener);
/** Deregisters a previously-registered listener. */
void removeListener (Listener* listener);
//==============================================================================
/** You can assign a lambda to this callback object to have it called when the label text is changed. */
std::function<void()> onTextChange;
/** You can assign a lambda to this callback object to have it called when the label's editor is shown. */
std::function<void()> onEditorShow;
/** You can assign a lambda to this callback object to have it called when the label's editor is hidden. */
std::function<void()> onEditorHide;
//==============================================================================
/** Makes the label turn into a TextEditor when clicked.
By default this is turned off.
If turned on, then single- or double-clicking will turn the label into
an editor. If the user then changes the text, then the ChangeBroadcaster
base class will be used to send change messages to any listeners that
have registered.
If the user changes the text, the textWasEdited() method will be called
afterwards, and subclasses can override this if they need to do anything
special.
@param editOnSingleClick if true, just clicking once on the label will start editing the text
@param editOnDoubleClick if true, a double-click is needed to start editing
@param lossOfFocusDiscardsChanges if true, clicking somewhere else while the text is being
edited will discard any changes; if false, then this will
commit the changes.
@see showEditor, setEditorColours, TextEditor
*/
void setEditable (bool editOnSingleClick,
bool editOnDoubleClick = false,
bool lossOfFocusDiscardsChanges = false);
/** Returns true if this option was set using setEditable(). */
bool isEditableOnSingleClick() const noexcept { return editSingleClick; }
/** Returns true if this option was set using setEditable(). */
bool isEditableOnDoubleClick() const noexcept { return editDoubleClick; }
/** Returns true if this option has been set in a call to setEditable(). */
bool doesLossOfFocusDiscardChanges() const noexcept { return lossOfFocusDiscardsChanges; }
/** Returns true if the user can edit this label's text. */
bool isEditable() const noexcept { return editSingleClick || editDoubleClick; }
/** Makes the editor appear as if the label had been clicked by the user.
@see textWasEdited, setEditable
*/
void showEditor();
/** Hides the editor if it was being shown.
@param discardCurrentEditorContents if true, the label's text will be
reset to whatever it was before the editor
was shown; if false, the current contents of the
editor will be used to set the label's text
before it is hidden.
*/
void hideEditor (bool discardCurrentEditorContents);
/** Returns true if the editor is currently focused and active. */
bool isBeingEdited() const noexcept;
/** Returns the currently-visible text editor, or nullptr if none is open. */
TextEditor* getCurrentTextEditor() const noexcept;
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes to provide
label drawing functionality.
*/
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawLabel (Graphics&, Label&) = 0;
virtual Font getLabelFont (Label&) = 0;
virtual BorderSize<int> getLabelBorderSize (Label&) = 0;
};
protected:
//==============================================================================
/** Creates the TextEditor component that will be used when the user has clicked on the label.
Subclasses can override this if they need to customise this component in some way.
*/
virtual TextEditor* createEditorComponent();
/** Called after the user changes the text. */
virtual void textWasEdited();
/** Called when the text has been altered. */
virtual void textWasChanged();
/** Called when the text editor has just appeared, due to a user click or other focus change. */
virtual void editorShown (TextEditor*);
/** Called when the text editor is going to be deleted, after editing has finished. */
virtual void editorAboutToBeHidden (TextEditor*);
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
void mouseDoubleClick (const MouseEvent&) override;
/** @internal */
void componentMovedOrResized (Component&, bool wasMoved, bool wasResized) override;
/** @internal */
void componentParentHierarchyChanged (Component&) override;
/** @internal */
void componentVisibilityChanged (Component&) override;
/** @internal */
void inputAttemptWhenModal() override;
/** @internal */
void focusGained (FocusChangeType) override;
/** @internal */
void enablementChanged() override;
/** @internal */
std::unique_ptr<ComponentTraverser> createKeyboardFocusTraverser() override;
/** @internal */
void textEditorTextChanged (TextEditor&) override;
/** @internal */
void textEditorReturnKeyPressed (TextEditor&) override;
/** @internal */
void textEditorEscapeKeyPressed (TextEditor&) override;
/** @internal */
void textEditorFocusLost (TextEditor&) override;
/** @internal */
void colourChanged() override;
/** @internal */
void valueChanged (Value&) override;
/** @internal */
void callChangeListeners();
private:
//==============================================================================
Value textValue;
String lastTextValue;
Font font { 15.0f };
Justification justification = Justification::centredLeft;
std::unique_ptr<TextEditor> editor;
ListenerList<Listener> listeners;
WeakReference<Component> ownerComponent;
BorderSize<int> border { 1, 5, 1, 5 };
float minimumHorizontalScale = 0;
TextInputTarget::VirtualKeyboardType keyboardType = TextInputTarget::textKeyboard;
bool editSingleClick = false;
bool editDoubleClick = false;
bool lossOfFocusDiscardsChanges = false;
bool leftOfOwnerComp = false;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
bool updateFromTextEditorContents (TextEditor&);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Label)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that displays a text string, and can optionally become a text
editor when clicked.
@tags{GUI}
*/
class JUCE_API Label : public Component,
public SettableTooltipClient,
protected TextEditor::Listener,
private ComponentListener,
private Value::Listener
{
public:
//==============================================================================
/** Creates a Label.
@param componentName the name to give the component
@param labelText the text to show in the label
*/
Label (const String& componentName = String(),
const String& labelText = String());
/** Destructor. */
~Label() override;
//==============================================================================
/** Changes the label text.
The NotificationType parameter indicates whether to send a change message to
any Label::Listener objects if the new text is different.
*/
void setText (const String& newText,
NotificationType notification);
/** Returns the label's current text.
@param returnActiveEditorContents if this is true and the label is currently
being edited, then this method will return the
text as it's being shown in the editor. If false,
then the value returned here won't be updated until
the user has finished typing and pressed the return
key.
*/
String getText (bool returnActiveEditorContents = false) const;
/** Returns the text content as a Value object.
You can call Value::referTo() on this object to make the label read and control
a Value object that you supply.
*/
Value& getTextValue() noexcept { return textValue; }
//==============================================================================
/** Changes the font to use to draw the text.
@see getFont
*/
void setFont (const Font& newFont);
/** Returns the font currently being used.
This may be the one set by setFont(), unless it has been overridden by the current LookAndFeel
@see setFont
*/
Font getFont() const noexcept;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the label.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
Note that you can also use the constants from TextEditor::ColourIds to change the
colour of the text editor that is opened when a label is editable.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */
textColourId = 0x1000281, /**< The colour for the text. */
outlineColourId = 0x1000282, /**< An optional colour to use to draw a border around the label.
Leave this transparent to not have an outline. */
backgroundWhenEditingColourId = 0x1000283, /**< The background colour when the label is being edited. */
textWhenEditingColourId = 0x1000284, /**< The colour for the text when the label is being edited. */
outlineWhenEditingColourId = 0x1000285 /**< An optional border colour when the label is being edited. */
};
//==============================================================================
/** Sets the style of justification to be used for positioning the text.
(The default is Justification::centredLeft)
*/
void setJustificationType (Justification justification);
/** Returns the type of justification, as set in setJustificationType(). */
Justification getJustificationType() const noexcept { return justification; }
/** Changes the border that is left between the edge of the component and the text.
By default there's a small gap left at the sides of the component to allow for
the drawing of the border, but you can change this if necessary.
*/
void setBorderSize (BorderSize<int> newBorderSize);
/** Returns the size of the border to be left around the text. */
BorderSize<int> getBorderSize() const noexcept { return border; }
/** Makes this label "stick to" another component.
This will cause the label to follow another component around, staying
either to its left or above it.
@param owner the component to follow
@param onLeft if true, the label will stay on the left of its component; if
false, it will stay above it.
*/
void attachToComponent (Component* owner, bool onLeft);
/** If this label has been attached to another component using attachToComponent, this
returns the other component.
Returns nullptr if the label is not attached.
*/
Component* getAttachedComponent() const;
/** If the label is attached to the left of another component, this returns true.
Returns false if the label is above the other component. This is only relevant if
attachToComponent() has been called.
*/
bool isAttachedOnLeft() const noexcept { return leftOfOwnerComp; }
/** Specifies the minimum amount that the font can be squashed horizontally before it starts
using ellipsis. Use a value of 0 for a default value.
@see Graphics::drawFittedText
*/
void setMinimumHorizontalScale (float newScale);
/** Specifies the amount that the font can be squashed horizontally. */
float getMinimumHorizontalScale() const noexcept { return minimumHorizontalScale; }
/** Set a keyboard type for use when the text editor is shown. */
void setKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept { keyboardType = type; }
//==============================================================================
/**
A class for receiving events from a Label.
You can register a Label::Listener with a Label using the Label::addListener()
method, and it will be called when the text of the label changes, either because
of a call to Label::setText() or by the user editing the text (if the label is
editable).
@see Label::addListener, Label::removeListener
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Called when a Label's text has changed. */
virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
/** Called when a Label goes into editing mode and displays a TextEditor. */
virtual void editorShown (Label*, TextEditor&) {}
/** Called when a Label is about to delete its TextEditor and exit editing mode. */
virtual void editorHidden (Label*, TextEditor&) {}
};
/** Registers a listener that will be called when the label's text changes. */
void addListener (Listener* listener);
/** Deregisters a previously-registered listener. */
void removeListener (Listener* listener);
//==============================================================================
/** You can assign a lambda to this callback object to have it called when the label text is changed. */
std::function<void()> onTextChange;
/** You can assign a lambda to this callback object to have it called when the label's editor is shown. */
std::function<void()> onEditorShow;
/** You can assign a lambda to this callback object to have it called when the label's editor is hidden. */
std::function<void()> onEditorHide;
//==============================================================================
/** Makes the label turn into a TextEditor when clicked.
By default this is turned off.
If turned on, then single- or double-clicking will turn the label into
an editor. If the user then changes the text, then the ChangeBroadcaster
base class will be used to send change messages to any listeners that
have registered.
If the user changes the text, the textWasEdited() method will be called
afterwards, and subclasses can override this if they need to do anything
special.
@param editOnSingleClick if true, just clicking once on the label will start editing the text
@param editOnDoubleClick if true, a double-click is needed to start editing
@param lossOfFocusDiscardsChanges if true, clicking somewhere else while the text is being
edited will discard any changes; if false, then this will
commit the changes.
@see showEditor, setEditorColours, TextEditor
*/
void setEditable (bool editOnSingleClick,
bool editOnDoubleClick = false,
bool lossOfFocusDiscardsChanges = false);
/** Returns true if this option was set using setEditable(). */
bool isEditableOnSingleClick() const noexcept { return editSingleClick; }
/** Returns true if this option was set using setEditable(). */
bool isEditableOnDoubleClick() const noexcept { return editDoubleClick; }
/** Returns true if this option has been set in a call to setEditable(). */
bool doesLossOfFocusDiscardChanges() const noexcept { return lossOfFocusDiscardsChanges; }
/** Returns true if the user can edit this label's text. */
bool isEditable() const noexcept { return editSingleClick || editDoubleClick; }
/** Makes the editor appear as if the label had been clicked by the user.
@see textWasEdited, setEditable
*/
void showEditor();
/** Hides the editor if it was being shown.
@param discardCurrentEditorContents if true, the label's text will be
reset to whatever it was before the editor
was shown; if false, the current contents of the
editor will be used to set the label's text
before it is hidden.
*/
void hideEditor (bool discardCurrentEditorContents);
/** Returns true if the editor is currently focused and active. */
bool isBeingEdited() const noexcept;
/** Returns the currently-visible text editor, or nullptr if none is open. */
TextEditor* getCurrentTextEditor() const noexcept;
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes to provide
label drawing functionality.
*/
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawLabel (Graphics&, Label&) = 0;
virtual Font getLabelFont (Label&) = 0;
virtual BorderSize<int> getLabelBorderSize (Label&) = 0;
};
protected:
//==============================================================================
/** Creates the TextEditor component that will be used when the user has clicked on the label.
Subclasses can override this if they need to customise this component in some way.
*/
virtual TextEditor* createEditorComponent();
/** Called after the user changes the text. */
virtual void textWasEdited();
/** Called when the text has been altered. */
virtual void textWasChanged();
/** Called when the text editor has just appeared, due to a user click or other focus change. */
virtual void editorShown (TextEditor*);
/** Called when the text editor is going to be deleted, after editing has finished. */
virtual void editorAboutToBeHidden (TextEditor*);
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
void mouseDoubleClick (const MouseEvent&) override;
/** @internal */
void componentMovedOrResized (Component&, bool wasMoved, bool wasResized) override;
/** @internal */
void componentParentHierarchyChanged (Component&) override;
/** @internal */
void componentVisibilityChanged (Component&) override;
/** @internal */
void inputAttemptWhenModal() override;
/** @internal */
void focusGained (FocusChangeType) override;
/** @internal */
void enablementChanged() override;
/** @internal */
std::unique_ptr<ComponentTraverser> createKeyboardFocusTraverser() override;
/** @internal */
void textEditorTextChanged (TextEditor&) override;
/** @internal */
void textEditorReturnKeyPressed (TextEditor&) override;
/** @internal */
void textEditorEscapeKeyPressed (TextEditor&) override;
/** @internal */
void textEditorFocusLost (TextEditor&) override;
/** @internal */
void colourChanged() override;
/** @internal */
void valueChanged (Value&) override;
/** @internal */
void callChangeListeners();
private:
//==============================================================================
Value textValue;
String lastTextValue;
Font font { 15.0f };
Justification justification = Justification::centredLeft;
std::unique_ptr<TextEditor> editor;
ListenerList<Listener> listeners;
WeakReference<Component> ownerComponent;
BorderSize<int> border { 1, 5, 1, 5 };
float minimumHorizontalScale = 0;
TextInputTarget::VirtualKeyboardType keyboardType = TextInputTarget::textKeyboard;
bool editSingleClick = false;
bool editDoubleClick = false;
bool lossOfFocusDiscardsChanges = false;
bool leftOfOwnerComp = false;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
bool updateFromTextEditorContents (TextEditor&);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Label)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

@ -1,60 +0,0 @@
diff a/modules/juce_gui_basics/widgets/juce_ListBox.cpp b/modules/juce_gui_basics/widgets/juce_ListBox.cpp (rejected hunks)
@@ -63,12 +63,15 @@ public:
void mouseDown (const MouseEvent& e) override
{
+ DBG("Listbox row mousedown");
isDragging = false;
selectRowOnMouseUp = false;
+ owner.stopInertialScroll();
+
if (isEnabled())
{
- if (owner.selectOnMouseDown && ! selected)
+ if (! selected && owner.selectOnMouseDown && !owner.getTouchScrollEnabled())
{
owner.selectRowsBasedOnModifierKeys (row, e.mods, false);
@@ -84,7 +87,16 @@ public:
void mouseUp (const MouseEvent& e) override
{
- if (isEnabled() && selectRowOnMouseUp && ! isDragging)
+ bool wasTouchScrolling = false;
+ if (owner.isTouchScrollActive()) {
+ wasTouchScrolling = true;
+ if (owner.getTouchScrollInertia() > 0.0f) {
+ owner.startInertialScroll();
+ }
+ owner.touchScrollDone();
+ }
+
+ if (isEnabled() && !wasTouchScrolling && selectRowOnMouseUp && !isDragging)
{
owner.selectRowsBasedOnModifierKeys (row, e.mods, true);
@@ -102,9 +114,10 @@ public:
void mouseDrag (const MouseEvent& e) override
{
+ bool touchdrag = owner.touchScrollDrag(e);
if (ListBoxModel* m = owner.getModel())
{
- if (isEnabled() && e.mouseWasDraggedSinceMouseDown() && ! isDragging)
+ if (!touchdrag && isEnabled() && e.mouseWasDraggedSinceMouseDown() && ! isDragging)
{
SparseSet<int> rowsToDrag;
@@ -367,6 +380,11 @@ private:
//==============================================================================
ListBox::ListBox (const String& name, ListBoxModel* const m)
: Component (name),
+ touchScrollEnabled(false),
+ touchScrolling(false),
+ scrollRate(0.0f),
+ touchScrollInertia(0.25f),
+ touchScrollScale(1.0f),
model (m),
totalItems (0),
rowHeight (22),

File diff suppressed because it is too large Load Diff

@ -1,172 +1,167 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ProgressBar::ProgressBar (double& progress_)
: progress (progress_),
displayPercentage (true),
lastCallbackTime (0)
{
currentValue = jlimit (0.0, 1.0, progress);
}
ProgressBar::~ProgressBar()
{
}
//==============================================================================
void ProgressBar::setPercentageDisplay (const bool shouldDisplayPercentage)
{
displayPercentage = shouldDisplayPercentage;
repaint();
}
void ProgressBar::setTextToDisplay (const String& text)
{
displayPercentage = false;
displayedMessage = text;
}
void ProgressBar::lookAndFeelChanged()
{
setOpaque (getLookAndFeel().isProgressBarOpaque (*this));
}
void ProgressBar::colourChanged()
{
lookAndFeelChanged();
}
void ProgressBar::paint (Graphics& g)
{
String text;
if (displayPercentage)
{
if (currentValue >= 0 && currentValue <= 1.0)
text << roundToInt (currentValue * 100.0) << '%';
}
else
{
text = displayedMessage;
}
getLookAndFeel().drawProgressBar (g, *this,
getWidth(), getHeight(),
currentValue, text);
}
void ProgressBar::visibilityChanged()
{
if (isVisible()) {
lastCallbackTime = Time::getMillisecondCounter();
currentValue = progress;
currentMessage = displayedMessage;
startTimer (30);
}
else {
stopTimer();
}
}
void ProgressBar::timerCallback()
{
double newProgress = progress;
const uint32 now = Time::getMillisecondCounter();
const int timeSinceLastCallback = (int) (now - lastCallbackTime);
lastCallbackTime = now;
if (currentValue != newProgress
|| newProgress < 0 || newProgress >= 1.0
|| currentMessage != displayedMessage)
{
if (currentValue < newProgress
&& newProgress >= 0 && newProgress < 1.0
&& currentValue >= 0 && currentValue < 1.0)
{
newProgress = jmin (currentValue + 0.004 * timeSinceLastCallback,
newProgress);
}
currentValue = newProgress;
currentMessage = displayedMessage;
repaint();
if (auto* handler = getAccessibilityHandler())
handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);
}
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ProgressBar::createAccessibilityHandler()
{
class ProgressBarAccessibilityHandler : public AccessibilityHandler
{
public:
explicit ProgressBarAccessibilityHandler (ProgressBar& progressBarToWrap)
: AccessibilityHandler (progressBarToWrap,
AccessibilityRole::progressBar,
AccessibilityActions{},
AccessibilityHandler::Interfaces { std::make_unique<ValueInterface> (progressBarToWrap) }),
progressBar (progressBarToWrap)
{
}
String getHelp() const override { return progressBar.getTooltip(); }
private:
class ValueInterface : public AccessibilityRangedNumericValueInterface
{
public:
explicit ValueInterface (ProgressBar& progressBarToWrap)
: progressBar (progressBarToWrap)
{
}
bool isReadOnly() const override { return true; }
void setValue (double) override { jassertfalse; }
double getCurrentValue() const override { return progressBar.progress; }
AccessibleValueRange getRange() const override { return { { 0.0, 1.0 }, 0.001 }; }
private:
ProgressBar& progressBar;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueInterface)
};
ProgressBar& progressBar;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgressBarAccessibilityHandler)
};
return std::make_unique<ProgressBarAccessibilityHandler> (*this);
}
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ProgressBar::ProgressBar (double& progress_)
: progress (progress_),
displayPercentage (true),
lastCallbackTime (0)
{
currentValue = jlimit (0.0, 1.0, progress);
}
ProgressBar::~ProgressBar()
{
}
//==============================================================================
void ProgressBar::setPercentageDisplay (const bool shouldDisplayPercentage)
{
displayPercentage = shouldDisplayPercentage;
repaint();
}
void ProgressBar::setTextToDisplay (const String& text)
{
displayPercentage = false;
displayedMessage = text;
}
void ProgressBar::lookAndFeelChanged()
{
setOpaque (getLookAndFeel().isProgressBarOpaque (*this));
}
void ProgressBar::colourChanged()
{
lookAndFeelChanged();
}
void ProgressBar::paint (Graphics& g)
{
String text;
if (displayPercentage)
{
if (currentValue >= 0 && currentValue <= 1.0)
text << roundToInt (currentValue * 100.0) << '%';
}
else
{
text = displayedMessage;
}
getLookAndFeel().drawProgressBar (g, *this,
getWidth(), getHeight(),
currentValue, text);
}
void ProgressBar::visibilityChanged()
{
if (isVisible())
startTimer (30);
else
stopTimer();
}
void ProgressBar::timerCallback()
{
double newProgress = progress;
const uint32 now = Time::getMillisecondCounter();
const int timeSinceLastCallback = (int) (now - lastCallbackTime);
lastCallbackTime = now;
if (currentValue != newProgress
|| newProgress < 0 || newProgress >= 1.0
|| currentMessage != displayedMessage)
{
if (currentValue < newProgress
&& newProgress >= 0 && newProgress < 1.0
&& currentValue >= 0 && currentValue < 1.0)
{
newProgress = jmin (currentValue + 0.0008 * timeSinceLastCallback,
newProgress);
}
currentValue = newProgress;
currentMessage = displayedMessage;
repaint();
if (auto* handler = getAccessibilityHandler())
handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);
}
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ProgressBar::createAccessibilityHandler()
{
class ProgressBarAccessibilityHandler : public AccessibilityHandler
{
public:
explicit ProgressBarAccessibilityHandler (ProgressBar& progressBarToWrap)
: AccessibilityHandler (progressBarToWrap,
AccessibilityRole::progressBar,
AccessibilityActions{},
AccessibilityHandler::Interfaces { std::make_unique<ValueInterface> (progressBarToWrap) }),
progressBar (progressBarToWrap)
{
}
String getHelp() const override { return progressBar.getTooltip(); }
private:
class ValueInterface : public AccessibilityRangedNumericValueInterface
{
public:
explicit ValueInterface (ProgressBar& progressBarToWrap)
: progressBar (progressBarToWrap)
{
}
bool isReadOnly() const override { return true; }
void setValue (double) override { jassertfalse; }
double getCurrentValue() const override { return progressBar.progress; }
AccessibleValueRange getRange() const override { return { { 0.0, 1.0 }, 0.001 }; }
private:
ProgressBar& progressBar;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueInterface)
};
ProgressBar& progressBar;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgressBarAccessibilityHandler)
};
return std::make_unique<ProgressBarAccessibilityHandler> (*this);
}
} // namespace juce

@ -1,144 +1,144 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A progress bar component.
To use this, just create one and make it visible. It'll run its own timer
to keep an eye on a variable that you give it, and will automatically
redraw itself when the variable changes.
If using LookAndFeel_V4 a circular spinning progress bar will be drawn if
the width and height of the ProgressBar are equal, otherwise the standard,
linear ProgressBar will be drawn.
For an easy way of running a background task with a dialog box showing its
progress, see the ThreadWithProgressWindow class.
@see ThreadWithProgressWindow
@tags{GUI}
*/
class JUCE_API ProgressBar : public Component,
public SettableTooltipClient,
private Timer
{
public:
//==============================================================================
/** Creates a ProgressBar.
@param progress pass in a reference to a double that you're going to
update with your task's progress. The ProgressBar will
monitor the value of this variable and will redraw itself
when the value changes. The range is from 0 to 1.0 and JUCE
LookAndFeel classes will draw a spinning animation for values
outside this range. Obviously you'd better be careful not to
delete this variable while the ProgressBar still exists!
*/
explicit ProgressBar (double& progress);
/** Destructor. */
~ProgressBar() override;
//==============================================================================
/** Turns the percentage display on or off.
By default this is on, and the progress bar will display a text string showing
its current percentage.
*/
void setPercentageDisplay (bool shouldDisplayPercentage);
/** Gives the progress bar a string to display inside it.
If you call this, it will turn off the percentage display.
@see setPercentageDisplay
*/
void setTextToDisplay (const String& text);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the bar.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1001900, /**< The background colour, behind the bar. */
foregroundColourId = 0x1001a00, /**< The colour to use to draw the bar itself. LookAndFeel
classes will probably use variations on this colour. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
/** Draws a progress bar.
If the progress value is less than 0 or greater than 1.0, this should draw a spinning
bar that fills the whole space (i.e. to say that the app is still busy but the progress
isn't known). It can use the current time as a basis for playing an animation.
(Used by progress bars in AlertWindow).
*/
virtual void drawProgressBar (Graphics&, ProgressBar&, int width, int height,
double progress, const String& textToShow) = 0;
virtual bool isProgressBarOpaque (ProgressBar&) = 0;
};
protected:
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void visibilityChanged() override;
/** @internal */
void colourChanged() override;
private:
double& progress;
double currentValue;
bool displayPercentage;
String displayedMessage, currentMessage;
uint32 lastCallbackTime;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void timerCallback() override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgressBar)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A progress bar component.
To use this, just create one and make it visible. It'll run its own timer
to keep an eye on a variable that you give it, and will automatically
redraw itself when the variable changes.
If using LookAndFeel_V4 a circular spinning progress bar will be drawn if
the width and height of the ProgressBar are equal, otherwise the standard,
linear ProgressBar will be drawn.
For an easy way of running a background task with a dialog box showing its
progress, see the ThreadWithProgressWindow class.
@see ThreadWithProgressWindow
@tags{GUI}
*/
class JUCE_API ProgressBar : public Component,
public SettableTooltipClient,
private Timer
{
public:
//==============================================================================
/** Creates a ProgressBar.
@param progress pass in a reference to a double that you're going to
update with your task's progress. The ProgressBar will
monitor the value of this variable and will redraw itself
when the value changes. The range is from 0 to 1.0 and JUCE
LookAndFeel classes will draw a spinning animation for values
outside this range. Obviously you'd better be careful not to
delete this variable while the ProgressBar still exists!
*/
explicit ProgressBar (double& progress);
/** Destructor. */
~ProgressBar() override;
//==============================================================================
/** Turns the percentage display on or off.
By default this is on, and the progress bar will display a text string showing
its current percentage.
*/
void setPercentageDisplay (bool shouldDisplayPercentage);
/** Gives the progress bar a string to display inside it.
If you call this, it will turn off the percentage display.
@see setPercentageDisplay
*/
void setTextToDisplay (const String& text);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the bar.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1001900, /**< The background colour, behind the bar. */
foregroundColourId = 0x1001a00, /**< The colour to use to draw the bar itself. LookAndFeel
classes will probably use variations on this colour. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
/** Draws a progress bar.
If the progress value is less than 0 or greater than 1.0, this should draw a spinning
bar that fills the whole space (i.e. to say that the app is still busy but the progress
isn't known). It can use the current time as a basis for playing an animation.
(Used by progress bars in AlertWindow).
*/
virtual void drawProgressBar (Graphics&, ProgressBar&, int width, int height,
double progress, const String& textToShow) = 0;
virtual bool isProgressBarOpaque (ProgressBar&) = 0;
};
protected:
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void visibilityChanged() override;
/** @internal */
void colourChanged() override;
private:
double& progress;
double currentValue;
bool displayPercentage;
String displayedMessage, currentMessage;
uint32 lastCallbackTime;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void timerCallback() override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgressBar)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,459 +1,461 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that displays a strip of column headings for a table, and allows these
to be resized, dragged around, etc.
This is just the component that goes at the top of a table. You can use it
directly for custom components, or to create a simple table, use the
TableListBox class.
To use one of these, create it and use addColumn() to add all the columns that you need.
Each column must be given a unique ID number that's used to refer to it.
@see TableListBox, TableHeaderComponent::Listener
@tags{GUI}
*/
class JUCE_API TableHeaderComponent : public Component,
private AsyncUpdater
{
public:
//==============================================================================
/** Creates an empty table header.
*/
TableHeaderComponent();
/** Destructor. */
~TableHeaderComponent() override;
//==============================================================================
/** A combination of these flags are passed into the addColumn() method to specify
the properties of a column.
*/
enum ColumnPropertyFlags
{
visible = 1, /**< If this is set, the column will be shown; if not, it will be hidden until the user enables it with the pop-up menu. */
resizable = 2, /**< If this is set, the column can be resized by dragging it. */
draggable = 4, /**< If this is set, the column can be dragged around to change its order in the table. */
appearsOnColumnMenu = 8, /**< If this is set, the column will be shown on the pop-up menu allowing it to be hidden/shown. */
sortable = 16, /**< If this is set, then clicking on the column header will set it to be the sort column, and clicking again will reverse the order. */
sortedForwards = 32, /**< If this is set, the column is currently the one by which the table is sorted (forwards). */
sortedBackwards = 64, /**< If this is set, the column is currently the one by which the table is sorted (backwards). */
/** This set of default flags is used as the default parameter value in addColumn(). */
defaultFlags = (visible | resizable | draggable | appearsOnColumnMenu | sortable),
/** A quick way of combining flags for a column that's not resizable. */
notResizable = (visible | draggable | appearsOnColumnMenu | sortable),
/** A quick way of combining flags for a column that's not resizable or sortable. */
notResizableOrSortable = (visible | draggable | appearsOnColumnMenu),
/** A quick way of combining flags for a column that's not sortable. */
notSortable = (visible | resizable | draggable | appearsOnColumnMenu)
};
/** Adds a column to the table.
This will add a column, and asynchronously call the tableColumnsChanged() method of any
registered listeners.
@param columnName the name of the new column. It's ok to have two or more columns with the same name
@param columnId an ID for this column. The ID can be any number apart from 0, but every column must have
a unique ID. This is used to identify the column later on, after the user may have
changed the order that they appear in
@param width the initial width of the column, in pixels
@param maximumWidth a maximum width that the column can take when the user is resizing it. This only applies
if the 'resizable' flag is specified for this column
@param minimumWidth a minimum width that the column can take when the user is resizing it. This only applies
if the 'resizable' flag is specified for this column
@param propertyFlags a combination of some of the values from the ColumnPropertyFlags enum, to define the
properties of this column
@param insertIndex the index at which the column should be added. A value of 0 puts it at the start (left-hand side)
and -1 puts it at the end (right-hand size) of the table. Note that the index the index within
all columns, not just the index amongst those that are currently visible
*/
void addColumn (const String& columnName,
int columnId,
int width,
int minimumWidth = 30,
int maximumWidth = -1,
int propertyFlags = defaultFlags,
int insertIndex = -1);
/** Removes a column with the given ID.
If there is such a column, this will asynchronously call the tableColumnsChanged() method of any
registered listeners.
*/
void removeColumn (int columnIdToRemove);
/** Deletes all columns from the table.
If there are any columns to remove, this will asynchronously call the tableColumnsChanged() method of any
registered listeners.
*/
void removeAllColumns();
/** Returns the number of columns in the table.
If onlyCountVisibleColumns is true, this will return the number of visible columns; otherwise it'll
return the total number of columns, including hidden ones.
@see isColumnVisible
*/
int getNumColumns (bool onlyCountVisibleColumns) const;
/** Returns the name for a column.
@see setColumnName
*/
String getColumnName (int columnId) const;
/** Changes the name of a column. */
void setColumnName (int columnId, const String& newName);
/** Moves a column to a different index in the table.
@param columnId the column to move
@param newVisibleIndex the target index for it, from 0 to the number of columns currently visible.
*/
void moveColumn (int columnId, int newVisibleIndex);
/** Returns the width of one of the columns.
*/
int getColumnWidth (int columnId) const;
/** Changes the width of a column.
This will cause an asynchronous callback to the tableColumnsResized() method of any registered listeners.
*/
void setColumnWidth (int columnId, int newWidth);
/** Shows or hides a column.
This can cause an asynchronous callback to the tableColumnsChanged() method of any registered listeners.
@see isColumnVisible
*/
void setColumnVisible (int columnId, bool shouldBeVisible);
/** Returns true if this column is currently visible.
@see setColumnVisible
*/
bool isColumnVisible (int columnId) const;
/** Changes the column which is the sort column.
This can cause an asynchronous callback to the tableSortOrderChanged() method of any registered listeners.
If this method doesn't actually change the column ID, then no re-sort will take place (you can
call reSortTable() to force a re-sort to happen if you've modified the table's contents).
@see getSortColumnId, isSortedForwards, reSortTable
*/
void setSortColumnId (int columnId, bool sortForwards);
/** Returns the column ID by which the table is currently sorted, or 0 if it is unsorted.
@see setSortColumnId, isSortedForwards
*/
int getSortColumnId() const;
/** Returns true if the table is currently sorted forwards, or false if it's backwards.
@see setSortColumnId
*/
bool isSortedForwards() const;
/** Triggers a re-sort of the table according to the current sort-column.
If you modify the table's contents, you can call this to signal that the table needs
to be re-sorted.
(This doesn't do any sorting synchronously - it just asynchronously sends a call to the
tableSortOrderChanged() method of any listeners).
*/
void reSortTable();
//==============================================================================
/** Returns the total width of all the visible columns in the table.
*/
int getTotalWidth() const;
/** Returns the index of a given column.
If there's no such column ID, this will return -1.
If onlyCountVisibleColumns is true, this will return the index amongst the visible columns;
otherwise it'll return the index amongst all the columns, including any hidden ones.
*/
int getIndexOfColumnId (int columnId, bool onlyCountVisibleColumns) const;
/** Returns the ID of the column at a given index.
If onlyCountVisibleColumns is true, this will count the index amongst the visible columns;
otherwise it'll count it amongst all the columns, including any hidden ones.
If the index is out-of-range, it'll return 0.
*/
int getColumnIdOfIndex (int index, bool onlyCountVisibleColumns) const;
/** Returns the rectangle containing of one of the columns.
The index is an index from 0 to the number of columns that are currently visible (hidden
ones are not counted). It returns a rectangle showing the position of the column relative
to this component's top-left. If the index is out-of-range, an empty rectangle is returned.
*/
Rectangle<int> getColumnPosition (int index) const;
/** Finds the column ID at a given x-position in the component.
If there is a column at this point this returns its ID, or if not, it will return 0.
*/
int getColumnIdAtX (int xToFind) const;
/** If set to true, this indicates that the columns should be expanded or shrunk to fill the
entire width of the component.
By default this is disabled. Turning it on also means that when resizing a column, those
on the right will be squashed to fit.
*/
void setStretchToFitActive (bool shouldStretchToFit);
/** Returns true if stretch-to-fit has been enabled.
@see setStretchToFitActive
*/
bool isStretchToFitActive() const;
/** If stretch-to-fit is enabled, this will resize all the columns to make them fit into the
specified width, keeping their relative proportions the same.
If the minimum widths of the columns are too wide to fit into this space, it may
actually end up wider.
*/
void resizeAllColumnsToFit (int targetTotalWidth);
//==============================================================================
/** Enables or disables the pop-up menu.
The default menu allows the user to show or hide columns. You can add custom
items to this menu by overloading the addMenuItems() and reactToMenuItem() methods.
By default the menu is enabled.
@see isPopupMenuActive, addMenuItems, reactToMenuItem
*/
void setPopupMenuActive (bool hasMenu);
/** Returns true if the pop-up menu is enabled.
@see setPopupMenuActive
*/
bool isPopupMenuActive() const;
//==============================================================================
/** Returns a string that encapsulates the table's current layout.
This can be restored later using restoreFromString(). It saves the order of
the columns, the currently-sorted column, and the widths.
@see restoreFromString
*/
String toString() const;
/** Restores the state of the table, based on a string previously created with
toString().
@see toString
*/
void restoreFromString (const String& storedVersion);
//==============================================================================
/**
Receives events from a TableHeaderComponent when columns are resized, moved, etc.
You can register one of these objects for table events using TableHeaderComponent::addListener()
and TableHeaderComponent::removeListener().
@see TableHeaderComponent
*/
class JUCE_API Listener
{
public:
//==============================================================================
Listener() = default;
/** Destructor. */
virtual ~Listener() = default;
//==============================================================================
/** This is called when some of the table's columns are added, removed, hidden,
or rearranged.
*/
virtual void tableColumnsChanged (TableHeaderComponent* tableHeader) = 0;
/** This is called when one or more of the table's columns are resized. */
virtual void tableColumnsResized (TableHeaderComponent* tableHeader) = 0;
/** This is called when the column by which the table should be sorted is changed. */
virtual void tableSortOrderChanged (TableHeaderComponent* tableHeader) = 0;
/** This is called when the user begins or ends dragging one of the columns around.
When the user starts dragging a column, this is called with the ID of that
column. When they finish dragging, it is called again with 0 as the ID.
*/
virtual void tableColumnDraggingChanged (TableHeaderComponent* tableHeader,
int columnIdNowBeingDragged);
};
/** Adds a listener to be informed about things that happen to the header. */
void addListener (Listener* newListener);
/** Removes a previously-registered listener. */
void removeListener (Listener* listenerToRemove);
//==============================================================================
/** This can be overridden to handle a mouse-click on one of the column headers.
The default implementation will use this click to call getSortColumnId() and
change the sort order.
*/
virtual void columnClicked (int columnId, const ModifierKeys& mods);
/** This can be overridden to add custom items to the pop-up menu.
If you override this, you should call the superclass's method to add its
column show/hide items, if you want them on the menu as well.
Then to handle the result, override reactToMenuItem().
@see reactToMenuItem
*/
virtual void addMenuItems (PopupMenu& menu, int columnIdClicked);
/** Override this to handle any custom items that you have added to the
pop-up menu with an addMenuItems() override.
If the menuReturnId isn't one of your own custom menu items, you'll need to
call TableHeaderComponent::reactToMenuItem() to allow the base class to
handle the items that it had added.
@see addMenuItems
*/
virtual void reactToMenuItem (int menuReturnId, int columnIdClicked);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the TableHeaderComponent.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
textColourId = 0x1003800, /**< The colour for the text in the header. */
backgroundColourId = 0x1003810, /**< The colour of the table header background.
It's up to the LookAndFeel how this is used. */
outlineColourId = 0x1003820, /**< The colour of the table header's outline. */
highlightColourId = 0x1003830, /**< The colour of the table header background when
the mouse is over or down above the the table
header. It's up to the LookAndFeel to use a
variant of this colour to distinguish between
the down and hover state. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) = 0;
virtual void drawTableHeaderColumn (Graphics&, TableHeaderComponent&,
const String& columnName, int columnId,
int width, int height,
bool isMouseOver, bool isMouseDown, int columnFlags) = 0;
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void mouseMove (const MouseEvent&) override;
/** @internal */
void mouseEnter (const MouseEvent&) override;
/** @internal */
void mouseExit (const MouseEvent&) override;
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
void mouseDrag (const MouseEvent&) override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
MouseCursor getMouseCursor() override;
/** Can be overridden for more control over the pop-up menu behaviour. */
virtual void showColumnChooserMenu (int columnIdClicked);
private:
struct ColumnInfo
{
String name;
int id, propertyFlags, width, minimumWidth, maximumWidth;
double lastDeliberateWidth;
bool isVisible() const;
};
OwnedArray<ColumnInfo> columns;
Array<Listener*> listeners;
std::unique_ptr<Component> dragOverlayComp;
class DragOverlayComp;
bool columnsChanged = false, columnsResized = false, sortChanged = false;
bool menuActive = true, stretchToFit = false;
int columnIdBeingResized = 0, columnIdBeingDragged = 0, initialColumnWidth = 0;
int columnIdUnderMouse = 0, draggingColumnOffset = 0, draggingColumnOriginalIndex = 0, lastDeliberateWidth = 0;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
ColumnInfo* getInfoForId (int columnId) const;
int visibleIndexToTotalIndex (int visibleIndex) const;
void sendColumnsChanged();
void handleAsyncUpdate() override;
void beginDrag (const MouseEvent&);
void endDrag (int finalIndex);
int getResizeDraggerAt (int mouseX) const;
void updateColumnUnderMouse (const MouseEvent&);
void setColumnUnderMouse (int columnId);
void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableHeaderComponent)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that displays a strip of column headings for a table, and allows these
to be resized, dragged around, etc.
This is just the component that goes at the top of a table. You can use it
directly for custom components, or to create a simple table, use the
TableListBox class.
To use one of these, create it and use addColumn() to add all the columns that you need.
Each column must be given a unique ID number that's used to refer to it.
@see TableListBox, TableHeaderComponent::Listener
@tags{GUI}
*/
class JUCE_API TableHeaderComponent : public Component,
private AsyncUpdater
{
public:
//==============================================================================
/** Creates an empty table header.
*/
TableHeaderComponent();
/** Destructor. */
~TableHeaderComponent() override;
//==============================================================================
/** A combination of these flags are passed into the addColumn() method to specify
the properties of a column.
*/
enum ColumnPropertyFlags
{
visible = 1, /**< If this is set, the column will be shown; if not, it will be hidden until the user enables it with the pop-up menu. */
resizable = 2, /**< If this is set, the column can be resized by dragging it. */
draggable = 4, /**< If this is set, the column can be dragged around to change its order in the table. */
appearsOnColumnMenu = 8, /**< If this is set, the column will be shown on the pop-up menu allowing it to be hidden/shown. */
sortable = 16, /**< If this is set, then clicking on the column header will set it to be the sort column, and clicking again will reverse the order. */
sortedForwards = 32, /**< If this is set, the column is currently the one by which the table is sorted (forwards). */
sortedBackwards = 64, /**< If this is set, the column is currently the one by which the table is sorted (backwards). */
/** This set of default flags is used as the default parameter value in addColumn(). */
defaultFlags = (visible | resizable | draggable | appearsOnColumnMenu | sortable),
/** A quick way of combining flags for a column that's not resizable. */
notResizable = (visible | draggable | appearsOnColumnMenu | sortable),
/** A quick way of combining flags for a column that's not resizable or sortable. */
notResizableOrSortable = (visible | draggable | appearsOnColumnMenu),
/** A quick way of combining flags for a column that's not sortable. */
notSortable = (visible | resizable | draggable | appearsOnColumnMenu)
};
/** Adds a column to the table.
This will add a column, and asynchronously call the tableColumnsChanged() method of any
registered listeners.
@param columnName the name of the new column. It's ok to have two or more columns with the same name
@param columnId an ID for this column. The ID can be any number apart from 0, but every column must have
a unique ID. This is used to identify the column later on, after the user may have
changed the order that they appear in
@param width the initial width of the column, in pixels
@param maximumWidth a maximum width that the column can take when the user is resizing it. This only applies
if the 'resizable' flag is specified for this column
@param minimumWidth a minimum width that the column can take when the user is resizing it. This only applies
if the 'resizable' flag is specified for this column
@param propertyFlags a combination of some of the values from the ColumnPropertyFlags enum, to define the
properties of this column
@param insertIndex the index at which the column should be added. A value of 0 puts it at the start (left-hand side)
and -1 puts it at the end (right-hand size) of the table. Note that the index the index within
all columns, not just the index amongst those that are currently visible
*/
void addColumn (const String& columnName,
int columnId,
int width,
int minimumWidth = 30,
int maximumWidth = -1,
int propertyFlags = defaultFlags,
int insertIndex = -1);
/** Removes a column with the given ID.
If there is such a column, this will asynchronously call the tableColumnsChanged() method of any
registered listeners.
*/
void removeColumn (int columnIdToRemove);
/** Deletes all columns from the table.
If there are any columns to remove, this will asynchronously call the tableColumnsChanged() method of any
registered listeners.
*/
void removeAllColumns();
/** Returns the number of columns in the table.
If onlyCountVisibleColumns is true, this will return the number of visible columns; otherwise it'll
return the total number of columns, including hidden ones.
@see isColumnVisible
*/
int getNumColumns (bool onlyCountVisibleColumns) const;
/** Returns the name for a column.
@see setColumnName
*/
String getColumnName (int columnId) const;
/** Changes the name of a column. */
void setColumnName (int columnId, const String& newName);
/** Moves a column to a different index in the table.
@param columnId the column to move
@param newVisibleIndex the target index for it, from 0 to the number of columns currently visible.
*/
void moveColumn (int columnId, int newVisibleIndex);
/** Returns the width of one of the columns.
*/
int getColumnWidth (int columnId) const;
/** Changes the width of a column.
This will cause an asynchronous callback to the tableColumnsResized() method of any registered listeners.
*/
void setColumnWidth (int columnId, int newWidth);
/** Shows or hides a column.
This can cause an asynchronous callback to the tableColumnsChanged() method of any registered listeners.
@see isColumnVisible
*/
void setColumnVisible (int columnId, bool shouldBeVisible);
/** Returns true if this column is currently visible.
@see setColumnVisible
*/
bool isColumnVisible (int columnId) const;
/** Changes the column which is the sort column.
This can cause an asynchronous callback to the tableSortOrderChanged() method of any registered listeners.
If this method doesn't actually change the column ID, then no re-sort will take place (you can
call reSortTable() to force a re-sort to happen if you've modified the table's contents).
@see getSortColumnId, isSortedForwards, reSortTable
*/
void setSortColumnId (int columnId, bool sortForwards);
/** Returns the column ID by which the table is currently sorted, or 0 if it is unsorted.
@see setSortColumnId, isSortedForwards
*/
int getSortColumnId() const;
/** Returns true if the table is currently sorted forwards, or false if it's backwards.
@see setSortColumnId
*/
bool isSortedForwards() const;
/** Triggers a re-sort of the table according to the current sort-column.
If you modify the table's contents, you can call this to signal that the table needs
to be re-sorted.
(This doesn't do any sorting synchronously - it just asynchronously sends a call to the
tableSortOrderChanged() method of any listeners).
*/
void reSortTable();
//==============================================================================
/** Returns the total width of all the visible columns in the table.
*/
int getTotalWidth() const;
/** Returns the index of a given column.
If there's no such column ID, this will return -1.
If onlyCountVisibleColumns is true, this will return the index amongst the visible columns;
otherwise it'll return the index amongst all the columns, including any hidden ones.
*/
int getIndexOfColumnId (int columnId, bool onlyCountVisibleColumns) const;
/** Returns the ID of the column at a given index.
If onlyCountVisibleColumns is true, this will count the index amongst the visible columns;
otherwise it'll count it amongst all the columns, including any hidden ones.
If the index is out-of-range, it'll return 0.
*/
int getColumnIdOfIndex (int index, bool onlyCountVisibleColumns) const;
/** Returns the rectangle containing of one of the columns.
The index is an index from 0 to the number of columns that are currently visible (hidden
ones are not counted). It returns a rectangle showing the position of the column relative
to this component's top-left. If the index is out-of-range, an empty rectangle is returned.
*/
Rectangle<int> getColumnPosition (int index) const;
/** Finds the column ID at a given x-position in the component.
If there is a column at this point this returns its ID, or if not, it will return 0.
*/
int getColumnIdAtX (int xToFind) const;
/** If set to true, this indicates that the columns should be expanded or shrunk to fill the
entire width of the component.
By default this is disabled. Turning it on also means that when resizing a column, those
on the right will be squashed to fit.
*/
void setStretchToFitActive (bool shouldStretchToFit);
/** Returns true if stretch-to-fit has been enabled.
@see setStretchToFitActive
*/
bool isStretchToFitActive() const;
/** If stretch-to-fit is enabled, this will resize all the columns to make them fit into the
specified width, keeping their relative proportions the same.
If the minimum widths of the columns are too wide to fit into this space, it may
actually end up wider.
*/
void resizeAllColumnsToFit (int targetTotalWidth);
//==============================================================================
/** Enables or disables the pop-up menu.
The default menu allows the user to show or hide columns. You can add custom
items to this menu by overloading the addMenuItems() and reactToMenuItem() methods.
By default the menu is enabled.
@see isPopupMenuActive, addMenuItems, reactToMenuItem
*/
void setPopupMenuActive (bool hasMenu);
/** Returns true if the pop-up menu is enabled.
@see setPopupMenuActive
*/
bool isPopupMenuActive() const;
//==============================================================================
/** Returns a string that encapsulates the table's current layout.
This can be restored later using restoreFromString(). It saves the order of
the columns, the currently-sorted column, and the widths.
@see restoreFromString
*/
String toString() const;
/** Restores the state of the table, based on a string previously created with
toString().
@see toString
*/
void restoreFromString (const String& storedVersion);
//==============================================================================
/**
Receives events from a TableHeaderComponent when columns are resized, moved, etc.
You can register one of these objects for table events using TableHeaderComponent::addListener()
and TableHeaderComponent::removeListener().
@see TableHeaderComponent
*/
class JUCE_API Listener
{
public:
//==============================================================================
Listener() = default;
/** Destructor. */
virtual ~Listener() = default;
//==============================================================================
/** This is called when some of the table's columns are added, removed, hidden,
or rearranged.
*/
virtual void tableColumnsChanged (TableHeaderComponent* tableHeader) = 0;
/** This is called when one or more of the table's columns are resized. */
virtual void tableColumnsResized (TableHeaderComponent* tableHeader) = 0;
/** This is called when the column by which the table should be sorted is changed. */
virtual void tableSortOrderChanged (TableHeaderComponent* tableHeader) = 0;
/** This is called when the user begins or ends dragging one of the columns around.
When the user starts dragging a column, this is called with the ID of that
column. When they finish dragging, it is called again with 0 as the ID.
*/
virtual void tableColumnDraggingChanged (TableHeaderComponent* tableHeader,
int columnIdNowBeingDragged);
};
/** Adds a listener to be informed about things that happen to the header. */
void addListener (Listener* newListener);
/** Removes a previously-registered listener. */
void removeListener (Listener* listenerToRemove);
//==============================================================================
/** This can be overridden to handle a mouse-click on one of the column headers.
The default implementation will use this click to call getSortColumnId() and
change the sort order.
*/
virtual void columnClicked (int columnId, const ModifierKeys& mods);
/** This can be overridden to add custom items to the pop-up menu.
If you override this, you should call the superclass's method to add its
column show/hide items, if you want them on the menu as well.
Then to handle the result, override reactToMenuItem().
@see reactToMenuItem
*/
virtual void addMenuItems (PopupMenu& menu, int columnIdClicked);
/** Override this to handle any custom items that you have added to the
pop-up menu with an addMenuItems() override.
If the menuReturnId isn't one of your own custom menu items, you'll need to
call TableHeaderComponent::reactToMenuItem() to allow the base class to
handle the items that it had added.
@see addMenuItems
*/
virtual void reactToMenuItem (int menuReturnId, int columnIdClicked);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the TableHeaderComponent.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
textColourId = 0x1003800, /**< The colour for the text in the header. */
backgroundColourId = 0x1003810, /**< The colour of the table header background.
It's up to the LookAndFeel how this is used. */
outlineColourId = 0x1003820, /**< The colour of the table header's outline. */
highlightColourId = 0x1003830, /**< The colour of the table header background when
the mouse is over or down above the the table
header. It's up to the LookAndFeel to use a
variant of this colour to distinguish between
the down and hover state. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) = 0;
virtual void drawTableHeaderColumn (Graphics&, TableHeaderComponent&,
const String& columnName, int columnId,
int width, int height,
bool isMouseOver, bool isMouseDown, int columnFlags) = 0;
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseMove (const MouseEvent&) override;
/** @internal */
void mouseEnter (const MouseEvent&) override;
/** @internal */
void mouseExit (const MouseEvent&) override;
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
void mouseDrag (const MouseEvent&) override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
MouseCursor getMouseCursor() override;
/** Can be overridden for more control over the pop-up menu behaviour. */
virtual void showColumnChooserMenu (int columnIdClicked);
private:
struct ColumnInfo : public Component
{
ColumnInfo() { setInterceptsMouseClicks (false, false); }
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
int id, propertyFlags, width, minimumWidth, maximumWidth;
double lastDeliberateWidth;
};
OwnedArray<ColumnInfo> columns;
Array<Listener*> listeners;
std::unique_ptr<Component> dragOverlayComp;
class DragOverlayComp;
bool columnsChanged = false, columnsResized = false, sortChanged = false;
bool menuActive = true, stretchToFit = false;
int columnIdBeingResized = 0, columnIdBeingDragged = 0, initialColumnWidth = 0;
int columnIdUnderMouse = 0, draggingColumnOffset = 0, draggingColumnOriginalIndex = 0, lastDeliberateWidth = 0;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
ColumnInfo* getInfoForId (int columnId) const;
int visibleIndexToTotalIndex (int visibleIndex) const;
void sendColumnsChanged();
void handleAsyncUpdate() override;
void beginDrag (const MouseEvent&);
void endDrag (int finalIndex);
int getResizeDraggerAt (int mouseX) const;
void updateColumnUnderMouse (const MouseEvent&);
void setColumnUnderMouse (int columnId);
void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableHeaderComponent)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

@ -1,346 +1,346 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
One of these is used by a TableListBox as the data model for the table's contents.
The virtual methods that you override in this class take care of drawing the
table cells, and reacting to events.
@see TableListBox
@tags{GUI}
*/
class JUCE_API TableListBoxModel
{
public:
//==============================================================================
TableListBoxModel() = default;
/** Destructor. */
virtual ~TableListBoxModel() = default;
//==============================================================================
/** This must return the number of rows currently in the table.
If the number of rows changes, you must call TableListBox::updateContent() to
cause it to refresh the list.
*/
virtual int getNumRows() = 0;
/** This must draw the background behind one of the rows in the table.
The graphics context has its origin at the row's top-left, and your method
should fill the area specified by the width and height parameters.
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintRowBackground (Graphics&,
int rowNumber,
int width, int height,
bool rowIsSelected) = 0;
/** This must draw one of the cells.
The graphics context's origin will already be set to the top-left of the cell,
whose size is specified by (width, height).
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintCell (Graphics&,
int rowNumber,
int columnId,
int width, int height,
bool rowIsSelected) = 0;
//==============================================================================
/** This is used to create or update a custom component to go in a cell.
Any cell may contain a custom component, or can just be drawn with the paintCell() method
and handle mouse clicks with cellClicked().
This method will be called whenever a custom component might need to be updated - e.g.
when the table is changed, or TableListBox::updateContent() is called.
If you don't need a custom component for the specified cell, then return nullptr.
(Bear in mind that even if you're not creating a new component, you may still need to
delete existingComponentToUpdate if it's non-null).
If you do want a custom component, and the existingComponentToUpdate is null, then
this method must create a new component suitable for the cell, and return it.
If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created
by this method. In this case, the method must either update it to make sure it's correctly representing
the given cell (which may be different from the one that the component was created for), or it can
delete this component and return a new one.
*/
virtual Component* refreshComponentForCell (int rowNumber, int columnId, bool isRowSelected,
Component* existingComponentToUpdate);
//==============================================================================
/** This callback is made when the user clicks on one of the cells in the table.
The mouse event's coordinates will be relative to the entire table row.
@see cellDoubleClicked, backgroundClicked
*/
virtual void cellClicked (int rowNumber, int columnId, const MouseEvent&);
/** This callback is made when the user clicks on one of the cells in the table.
The mouse event's coordinates will be relative to the entire table row.
@see cellClicked, backgroundClicked
*/
virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent&);
/** This can be overridden to react to the user double-clicking on a part of the list where
there are no rows.
@see cellClicked
*/
virtual void backgroundClicked (const MouseEvent&);
//==============================================================================
/** This callback is made when the table's sort order is changed.
This could be because the user has clicked a column header, or because the
TableHeaderComponent::setSortColumnId() method was called.
If you implement this, your method should re-sort the table using the given
column as the key.
*/
virtual void sortOrderChanged (int newSortColumnId, bool isForwards);
//==============================================================================
/** Returns the best width for one of the columns.
If you implement this method, you should measure the width of all the items
in this column, and return the best size.
Returning 0 means that the column shouldn't be changed.
This is used by TableListBox::autoSizeColumn() and TableListBox::autoSizeAllColumns().
*/
virtual int getColumnAutoSizeWidth (int columnId);
/** Returns a tooltip for a particular cell in the table. */
virtual String getCellTooltip (int rowNumber, int columnId);
//==============================================================================
/** Override this to be informed when rows are selected or deselected.
@see ListBox::selectedRowsChanged()
*/
virtual void selectedRowsChanged (int lastRowSelected);
/** Override this to be informed when the delete key is pressed.
@see ListBox::deleteKeyPressed()
*/
virtual void deleteKeyPressed (int lastRowSelected);
/** Override this to be informed when the return key is pressed.
@see ListBox::returnKeyPressed()
*/
virtual void returnKeyPressed (int lastRowSelected);
/** Override this to be informed when the list is scrolled.
This might be caused by the user moving the scrollbar, or by programmatic changes
to the list position.
*/
virtual void listWasScrolled();
/** To allow rows from your table to be dragged-and-dropped, implement this method.
If this returns a non-null variant then when the user drags a row, the table will try to
find a DragAndDropContainer in its parent hierarchy, and will use it to trigger a
drag-and-drop operation, using this string as the source description, and the listbox
itself as the source component.
@see getDragSourceCustomData, DragAndDropContainer::startDragging
*/
virtual var getDragSourceDescription (const SparseSet<int>& currentlySelectedRows);
};
//==============================================================================
/**
A table of cells, using a TableHeaderComponent as its header.
This component makes it easy to create a table by providing a TableListBoxModel as
the data source.
@see TableListBoxModel, TableHeaderComponent
@tags{GUI}
*/
class JUCE_API TableListBox : public ListBox,
private ListBoxModel,
private TableHeaderComponent::Listener
{
public:
//==============================================================================
/** Creates a TableListBox.
The model pointer passed-in can be null, in which case you can set it later
with setModel(). The TableListBox does not take ownership of the model - it's
the caller's responsibility to manage its lifetime and make sure it
doesn't get deleted while still being used.
*/
TableListBox (const String& componentName = String(),
TableListBoxModel* model = nullptr);
/** Destructor. */
~TableListBox() override;
//==============================================================================
/** Changes the TableListBoxModel that is being used for this table.
The TableListBox does not take ownership of the model - it's the caller's responsibility
to manage its lifetime and make sure it doesn't get deleted while still being used.
*/
void setModel (TableListBoxModel* newModel);
/** Returns the model currently in use. */
TableListBoxModel* getModel() const noexcept { return model; }
//==============================================================================
/** Returns the header component being used in this table. */
TableHeaderComponent& getHeader() const noexcept { return *header; }
/** Sets the header component to use for the table.
The table will take ownership of the component that you pass in, and will delete it
when it's no longer needed.
The pointer passed in may not be null.
*/
void setHeader (std::unique_ptr<TableHeaderComponent> newHeader);
/** Changes the height of the table header component.
@see getHeaderHeight
*/
void setHeaderHeight (int newHeight);
/** Returns the height of the table header.
@see setHeaderHeight
*/
int getHeaderHeight() const noexcept;
//==============================================================================
/** Resizes a column to fit its contents.
This uses TableListBoxModel::getColumnAutoSizeWidth() to find the best width,
and applies that to the column.
@see autoSizeAllColumns, TableHeaderComponent::setColumnWidth
*/
void autoSizeColumn (int columnId);
/** Calls autoSizeColumn() for all columns in the table. */
void autoSizeAllColumns();
/** Enables or disables the auto size options on the popup menu.
By default, these are enabled.
*/
void setAutoSizeMenuOptionShown (bool shouldBeShown) noexcept;
/** True if the auto-size options should be shown on the menu.
@see setAutoSizeMenuOptionShown
*/
bool isAutoSizeMenuOptionShown() const noexcept { return autoSizeOptionsShown; }
/** Returns the position of one of the cells in the table.
If relativeToComponentTopLeft is true, the coordinates are relative to
the table component's top-left. The row number isn't checked to see if it's
in-range, but the column ID must exist or this will return an empty rectangle.
If relativeToComponentTopLeft is false, the coordinates are relative to the
top-left of the table's top-left cell.
*/
Rectangle<int> getCellPosition (int columnId, int rowNumber,
bool relativeToComponentTopLeft) const;
/** Returns the component that currently represents a given cell.
If the component for this cell is off-screen or if the position is out-of-range,
this may return nullptr.
@see getCellPosition
*/
Component* getCellComponent (int columnId, int rowNumber) const;
/** Scrolls horizontally if necessary to make sure that a particular column is visible.
@see ListBox::scrollToEnsureRowIsOnscreen
*/
void scrollToEnsureColumnIsOnscreen (int columnId);
//==============================================================================
/** @internal */
int getNumRows() override;
/** @internal */
void paintListBoxItem (int, Graphics&, int, int, bool) override;
/** @internal */
Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) override;
/** @internal */
void selectedRowsChanged (int row) override;
/** @internal */
void deleteKeyPressed (int currentSelectedRow) override;
/** @internal */
void returnKeyPressed (int currentSelectedRow) override;
/** @internal */
void backgroundClicked (const MouseEvent&) override;
/** @internal */
void listWasScrolled() override;
/** @internal */
void tableColumnsChanged (TableHeaderComponent*) override;
/** @internal */
void tableColumnsResized (TableHeaderComponent*) override;
/** @internal */
void tableSortOrderChanged (TableHeaderComponent*) override;
/** @internal */
void tableColumnDraggingChanged (TableHeaderComponent*, int) override;
/** @internal */
void resized() override;
private:
//==============================================================================
class Header;
class RowComp;
TableHeaderComponent* header = nullptr;
TableListBoxModel* model;
int columnIdNowBeingDragged = 0;
bool autoSizeOptionsShown = true;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void updateColumnComponents() const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableListBox)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
One of these is used by a TableListBox as the data model for the table's contents.
The virtual methods that you override in this class take care of drawing the
table cells, and reacting to events.
@see TableListBox
@tags{GUI}
*/
class JUCE_API TableListBoxModel
{
public:
//==============================================================================
TableListBoxModel() = default;
/** Destructor. */
virtual ~TableListBoxModel() = default;
//==============================================================================
/** This must return the number of rows currently in the table.
If the number of rows changes, you must call TableListBox::updateContent() to
cause it to refresh the list.
*/
virtual int getNumRows() = 0;
/** This must draw the background behind one of the rows in the table.
The graphics context has its origin at the row's top-left, and your method
should fill the area specified by the width and height parameters.
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintRowBackground (Graphics&,
int rowNumber,
int width, int height,
bool rowIsSelected) = 0;
/** This must draw one of the cells.
The graphics context's origin will already be set to the top-left of the cell,
whose size is specified by (width, height).
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintCell (Graphics&,
int rowNumber,
int columnId,
int width, int height,
bool rowIsSelected) = 0;
//==============================================================================
/** This is used to create or update a custom component to go in a cell.
Any cell may contain a custom component, or can just be drawn with the paintCell() method
and handle mouse clicks with cellClicked().
This method will be called whenever a custom component might need to be updated - e.g.
when the table is changed, or TableListBox::updateContent() is called.
If you don't need a custom component for the specified cell, then return nullptr.
(Bear in mind that even if you're not creating a new component, you may still need to
delete existingComponentToUpdate if it's non-null).
If you do want a custom component, and the existingComponentToUpdate is null, then
this method must create a new component suitable for the cell, and return it.
If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created
by this method. In this case, the method must either update it to make sure it's correctly representing
the given cell (which may be different from the one that the component was created for), or it can
delete this component and return a new one.
*/
virtual Component* refreshComponentForCell (int rowNumber, int columnId, bool isRowSelected,
Component* existingComponentToUpdate);
//==============================================================================
/** This callback is made when the user clicks on one of the cells in the table.
The mouse event's coordinates will be relative to the entire table row.
@see cellDoubleClicked, backgroundClicked
*/
virtual void cellClicked (int rowNumber, int columnId, const MouseEvent&);
/** This callback is made when the user clicks on one of the cells in the table.
The mouse event's coordinates will be relative to the entire table row.
@see cellClicked, backgroundClicked
*/
virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent&);
/** This can be overridden to react to the user double-clicking on a part of the list where
there are no rows.
@see cellClicked
*/
virtual void backgroundClicked (const MouseEvent&);
//==============================================================================
/** This callback is made when the table's sort order is changed.
This could be because the user has clicked a column header, or because the
TableHeaderComponent::setSortColumnId() method was called.
If you implement this, your method should re-sort the table using the given
column as the key.
*/
virtual void sortOrderChanged (int newSortColumnId, bool isForwards);
//==============================================================================
/** Returns the best width for one of the columns.
If you implement this method, you should measure the width of all the items
in this column, and return the best size.
Returning 0 means that the column shouldn't be changed.
This is used by TableListBox::autoSizeColumn() and TableListBox::autoSizeAllColumns().
*/
virtual int getColumnAutoSizeWidth (int columnId);
/** Returns a tooltip for a particular cell in the table. */
virtual String getCellTooltip (int rowNumber, int columnId);
//==============================================================================
/** Override this to be informed when rows are selected or deselected.
@see ListBox::selectedRowsChanged()
*/
virtual void selectedRowsChanged (int lastRowSelected);
/** Override this to be informed when the delete key is pressed.
@see ListBox::deleteKeyPressed()
*/
virtual void deleteKeyPressed (int lastRowSelected);
/** Override this to be informed when the return key is pressed.
@see ListBox::returnKeyPressed()
*/
virtual void returnKeyPressed (int lastRowSelected);
/** Override this to be informed when the list is scrolled.
This might be caused by the user moving the scrollbar, or by programmatic changes
to the list position.
*/
virtual void listWasScrolled();
/** To allow rows from your table to be dragged-and-dropped, implement this method.
If this returns a non-null variant then when the user drags a row, the table will try to
find a DragAndDropContainer in its parent hierarchy, and will use it to trigger a
drag-and-drop operation, using this string as the source description, and the listbox
itself as the source component.
@see getDragSourceCustomData, DragAndDropContainer::startDragging
*/
virtual var getDragSourceDescription (const SparseSet<int>& currentlySelectedRows);
};
//==============================================================================
/**
A table of cells, using a TableHeaderComponent as its header.
This component makes it easy to create a table by providing a TableListBoxModel as
the data source.
@see TableListBoxModel, TableHeaderComponent
@tags{GUI}
*/
class JUCE_API TableListBox : public ListBox,
private ListBoxModel,
private TableHeaderComponent::Listener
{
public:
//==============================================================================
/** Creates a TableListBox.
The model pointer passed-in can be null, in which case you can set it later
with setModel(). The TableListBox does not take ownership of the model - it's
the caller's responsibility to manage its lifetime and make sure it
doesn't get deleted while still being used.
*/
TableListBox (const String& componentName = String(),
TableListBoxModel* model = nullptr);
/** Destructor. */
~TableListBox() override;
//==============================================================================
/** Changes the TableListBoxModel that is being used for this table.
The TableListBox does not take ownership of the model - it's the caller's responsibility
to manage its lifetime and make sure it doesn't get deleted while still being used.
*/
void setModel (TableListBoxModel* newModel);
/** Returns the model currently in use. */
TableListBoxModel* getModel() const noexcept { return model; }
//==============================================================================
/** Returns the header component being used in this table. */
TableHeaderComponent& getHeader() const noexcept { return *header; }
/** Sets the header component to use for the table.
The table will take ownership of the component that you pass in, and will delete it
when it's no longer needed.
The pointer passed in may not be null.
*/
void setHeader (std::unique_ptr<TableHeaderComponent> newHeader);
/** Changes the height of the table header component.
@see getHeaderHeight
*/
void setHeaderHeight (int newHeight);
/** Returns the height of the table header.
@see setHeaderHeight
*/
int getHeaderHeight() const noexcept;
//==============================================================================
/** Resizes a column to fit its contents.
This uses TableListBoxModel::getColumnAutoSizeWidth() to find the best width,
and applies that to the column.
@see autoSizeAllColumns, TableHeaderComponent::setColumnWidth
*/
void autoSizeColumn (int columnId);
/** Calls autoSizeColumn() for all columns in the table. */
void autoSizeAllColumns();
/** Enables or disables the auto size options on the popup menu.
By default, these are enabled.
*/
void setAutoSizeMenuOptionShown (bool shouldBeShown) noexcept;
/** True if the auto-size options should be shown on the menu.
@see setAutoSizeMenuOptionShown
*/
bool isAutoSizeMenuOptionShown() const noexcept { return autoSizeOptionsShown; }
/** Returns the position of one of the cells in the table.
If relativeToComponentTopLeft is true, the coordinates are relative to
the table component's top-left. The row number isn't checked to see if it's
in-range, but the column ID must exist or this will return an empty rectangle.
If relativeToComponentTopLeft is false, the coordinates are relative to the
top-left of the table's top-left cell.
*/
Rectangle<int> getCellPosition (int columnId, int rowNumber,
bool relativeToComponentTopLeft) const;
/** Returns the component that currently represents a given cell.
If the component for this cell is off-screen or if the position is out-of-range,
this may return nullptr.
@see getCellPosition
*/
Component* getCellComponent (int columnId, int rowNumber) const;
/** Scrolls horizontally if necessary to make sure that a particular column is visible.
@see ListBox::scrollToEnsureRowIsOnscreen
*/
void scrollToEnsureColumnIsOnscreen (int columnId);
//==============================================================================
/** @internal */
int getNumRows() override;
/** @internal */
void paintListBoxItem (int, Graphics&, int, int, bool) override;
/** @internal */
Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) override;
/** @internal */
void selectedRowsChanged (int row) override;
/** @internal */
void deleteKeyPressed (int currentSelectedRow) override;
/** @internal */
void returnKeyPressed (int currentSelectedRow) override;
/** @internal */
void backgroundClicked (const MouseEvent&) override;
/** @internal */
void listWasScrolled() override;
/** @internal */
void tableColumnsChanged (TableHeaderComponent*) override;
/** @internal */
void tableColumnsResized (TableHeaderComponent*) override;
/** @internal */
void tableSortOrderChanged (TableHeaderComponent*) override;
/** @internal */
void tableColumnDraggingChanged (TableHeaderComponent*, int) override;
/** @internal */
void resized() override;
private:
//==============================================================================
class Header;
class RowComp;
TableHeaderComponent* header = nullptr;
TableListBoxModel* model;
int columnIdNowBeingDragged = 0;
bool autoSizeOptionsShown = true;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void updateColumnComponents() const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableListBox)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,334 +1,335 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class ToolbarItemComponent;
class ToolbarItemFactory;
//==============================================================================
/**
A toolbar component.
A toolbar contains a horizontal or vertical strip of ToolbarItemComponents,
and looks after their order and layout.
Items (icon buttons or other custom components) are added to a toolbar using a
ToolbarItemFactory - each type of item is given a unique ID number, and a
toolbar might contain more than one instance of a particular item type.
Toolbars can be interactively customised, allowing the user to drag the items
around, and to drag items onto or off the toolbar, using the ToolbarItemPalette
component as a source of new items.
@see ToolbarItemFactory, ToolbarItemComponent, ToolbarItemPalette
@tags{GUI}
*/
class JUCE_API Toolbar : public Component,
public DragAndDropContainer,
public DragAndDropTarget
{
public:
//==============================================================================
/** Creates an empty toolbar component.
To add some icons or other components to your toolbar, you'll need to
create a ToolbarItemFactory class that can create a suitable set of
ToolbarItemComponents.
@see ToolbarItemFactory, ToolbarItemComponents
*/
Toolbar();
/** Destructor.
Any items on the bar will be deleted when the toolbar is deleted.
*/
~Toolbar() override;
//==============================================================================
/** Changes the bar's orientation.
@see isVertical
*/
void setVertical (bool shouldBeVertical);
/** Returns true if the bar is set to be vertical, or false if it's horizontal.
You can change the bar's orientation with setVertical().
*/
bool isVertical() const noexcept { return vertical; }
/** Returns the depth of the bar.
If the bar is horizontal, this will return its height; if it's vertical, it
will return its width.
@see getLength
*/
int getThickness() const noexcept;
/** Returns the length of the bar.
If the bar is horizontal, this will return its width; if it's vertical, it
will return its height.
@see getThickness
*/
int getLength() const noexcept;
//==============================================================================
/** Deletes all items from the bar.
*/
void clear();
/** Adds an item to the toolbar.
The factory's ToolbarItemFactory::createItem() will be called by this method
to create the component that will actually be added to the bar.
The new item will be inserted at the specified index (if the index is -1, it
will be added to the right-hand or bottom end of the bar).
Once added, the component will be automatically deleted by this object when it
is no longer needed.
@see ToolbarItemFactory
*/
void addItem (ToolbarItemFactory& factory,
int itemId,
int insertIndex = -1);
/** Deletes one of the items from the bar. */
void removeToolbarItem (int itemIndex);
/** Removes an item from the bar and returns it. */
ToolbarItemComponent* removeAndReturnItem (int itemIndex);
/** Returns the number of items currently on the toolbar.
@see getItemId, getItemComponent
*/
int getNumItems() const noexcept;
/** Returns the ID of the item with the given index.
If the index is less than zero or greater than the number of items,
this will return nullptr.
@see getNumItems
*/
int getItemId (int itemIndex) const noexcept;
/** Returns the component being used for the item with the given index.
If the index is less than zero or greater than the number of items,
this will return nullptr.
@see getNumItems
*/
ToolbarItemComponent* getItemComponent (int itemIndex) const noexcept;
/** Clears this toolbar and adds to it the default set of items that the specified
factory creates.
@see ToolbarItemFactory::getDefaultItemSet
*/
void addDefaultItems (ToolbarItemFactory& factoryToUse);
//==============================================================================
/** Options for the way items should be displayed.
@see setStyle, getStyle
*/
enum ToolbarItemStyle
{
iconsOnly, /**< Means that the toolbar should just contain icons. */
iconsWithText, /**< Means that the toolbar should have text labels under each icon. */
textOnly /**< Means that the toolbar only display text labels for each item. */
};
/** Returns the toolbar's current style.
@see ToolbarItemStyle, setStyle
*/
ToolbarItemStyle getStyle() const noexcept { return toolbarStyle; }
/** Changes the toolbar's current style.
@see ToolbarItemStyle, getStyle, ToolbarItemComponent::setStyle
*/
void setStyle (const ToolbarItemStyle& newStyle);
//==============================================================================
/** Flags used by the showCustomisationDialog() method. */
enum CustomisationFlags
{
allowIconsOnlyChoice = 1, /**< If this flag is specified, the customisation dialog can
show the "icons only" option on its choice of toolbar styles. */
allowIconsWithTextChoice = 2, /**< If this flag is specified, the customisation dialog can
show the "icons with text" option on its choice of toolbar styles. */
allowTextOnlyChoice = 4, /**< If this flag is specified, the customisation dialog can
show the "text only" option on its choice of toolbar styles. */
showResetToDefaultsButton = 8, /**< If this flag is specified, the customisation dialog can
show a button to reset the toolbar to its default set of items. */
allCustomisationOptionsEnabled = (allowIconsOnlyChoice | allowIconsWithTextChoice | allowTextOnlyChoice | showResetToDefaultsButton)
};
/** Pops up a modal dialog box that allows this toolbar to be customised by the user.
The dialog contains a ToolbarItemPalette and various controls for editing other
aspects of the toolbar. The dialog box will be opened modally, but the method will
return immediately.
The factory is used to determine the set of items that will be shown on the
palette.
The optionFlags parameter is a bitwise-or of values from the CustomisationFlags
enum.
@see ToolbarItemPalette
*/
void showCustomisationDialog (ToolbarItemFactory& factory,
int optionFlags = allCustomisationOptionsEnabled);
/** Turns on or off the toolbar's editing mode, in which its items can be
rearranged by the user.
(In most cases it's easier just to use showCustomisationDialog() instead of
trying to enable editing directly).
@see ToolbarItemPalette
*/
void setEditingActive (bool editingEnabled);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the toolbar.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1003200, /**< A colour to use to fill the toolbar's background. For
more control over this, override LookAndFeel::paintToolbarBackground(). */
separatorColourId = 0x1003210, /**< A colour to use to draw the separator lines. */
buttonMouseOverBackgroundColourId = 0x1003220, /**< A colour used to paint the background of buttons when the mouse is
over them. */
buttonMouseDownBackgroundColourId = 0x1003230, /**< A colour used to paint the background of buttons when the mouse is
held down on them. */
labelTextColourId = 0x1003240, /**< A colour to use for drawing the text under buttons
when the style is set to iconsWithText or textOnly. */
editingModeOutlineColourId = 0x1003250 /**< A colour to use for an outline around buttons when
the customisation dialog is active and the mouse moves over them. */
};
//==============================================================================
/** Returns a string that represents the toolbar's current set of items.
This lets you later restore the same item layout using restoreFromString().
@see restoreFromString
*/
String toString() const;
/** Restores a set of items that was previously stored in a string by the toString()
method.
The factory object is used to create any item components that are needed.
@see toString
*/
bool restoreFromString (ToolbarItemFactory& factoryToUse,
const String& savedVersion);
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void paintToolbarBackground (Graphics&, int width, int height, Toolbar&) = 0;
virtual Button* createToolbarMissingItemsButton (Toolbar&) = 0;
virtual void paintToolbarButtonBackground (Graphics&, int width, int height,
bool isMouseOver, bool isMouseDown,
ToolbarItemComponent&) = 0;
virtual void paintToolbarButtonLabel (Graphics&, int x, int y, int width, int height,
const String& text, ToolbarItemComponent&) = 0;
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
bool isInterestedInDragSource (const SourceDetails&) override;
/** @internal */
void itemDragMove (const SourceDetails&) override;
/** @internal */
void itemDragExit (const SourceDetails&) override;
/** @internal */
void itemDropped (const SourceDetails&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void updateAllItemPositions (bool animate);
/** @internal */
static ToolbarItemComponent* createItem (ToolbarItemFactory&, int itemId);
/** @internal */
static const char* const toolbarDragDescriptor;
private:
//==============================================================================
std::unique_ptr<Button> missingItemsButton;
bool vertical = false, isEditingActive = false;
ToolbarItemStyle toolbarStyle = iconsOnly;
class MissingItemsComponent;
friend class MissingItemsComponent;
OwnedArray<ToolbarItemComponent> items;
class Spacer;
class CustomisationDialog;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void showMissingItems();
void addItemInternal (ToolbarItemFactory& factory, int itemId, int insertIndex);
ToolbarItemComponent* getNextActiveComponent (int index, int delta) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Toolbar)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
class ToolbarItemComponent;
class ToolbarItemFactory;
//==============================================================================
/**
A toolbar component.
A toolbar contains a horizontal or vertical strip of ToolbarItemComponents,
and looks after their order and layout.
Items (icon buttons or other custom components) are added to a toolbar using a
ToolbarItemFactory - each type of item is given a unique ID number, and a
toolbar might contain more than one instance of a particular item type.
Toolbars can be interactively customised, allowing the user to drag the items
around, and to drag items onto or off the toolbar, using the ToolbarItemPalette
component as a source of new items.
@see ToolbarItemFactory, ToolbarItemComponent, ToolbarItemPalette
@tags{GUI}
*/
class JUCE_API Toolbar : public Component,
public DragAndDropContainer,
public DragAndDropTarget
{
public:
//==============================================================================
/** Creates an empty toolbar component.
To add some icons or other components to your toolbar, you'll need to
create a ToolbarItemFactory class that can create a suitable set of
ToolbarItemComponents.
@see ToolbarItemFactory, ToolbarItemComponents
*/
Toolbar();
/** Destructor.
Any items on the bar will be deleted when the toolbar is deleted.
*/
~Toolbar() override;
//==============================================================================
/** Changes the bar's orientation.
@see isVertical
*/
void setVertical (bool shouldBeVertical);
/** Returns true if the bar is set to be vertical, or false if it's horizontal.
You can change the bar's orientation with setVertical().
*/
bool isVertical() const noexcept { return vertical; }
/** Returns the depth of the bar.
If the bar is horizontal, this will return its height; if it's vertical, it
will return its width.
@see getLength
*/
int getThickness() const noexcept;
/** Returns the length of the bar.
If the bar is horizontal, this will return its width; if it's vertical, it
will return its height.
@see getThickness
*/
int getLength() const noexcept;
//==============================================================================
/** Deletes all items from the bar.
*/
void clear();
/** Adds an item to the toolbar.
The factory's ToolbarItemFactory::createItem() will be called by this method
to create the component that will actually be added to the bar.
The new item will be inserted at the specified index (if the index is -1, it
will be added to the right-hand or bottom end of the bar).
Once added, the component will be automatically deleted by this object when it
is no longer needed.
@see ToolbarItemFactory
*/
void addItem (ToolbarItemFactory& factory,
int itemId,
int insertIndex = -1);
/** Deletes one of the items from the bar. */
void removeToolbarItem (int itemIndex);
/** Removes an item from the bar and returns it. */
ToolbarItemComponent* removeAndReturnItem (int itemIndex);
/** Returns the number of items currently on the toolbar.
@see getItemId, getItemComponent
*/
int getNumItems() const noexcept;
/** Returns the ID of the item with the given index.
If the index is less than zero or greater than the number of items,
this will return nullptr.
@see getNumItems
*/
int getItemId (int itemIndex) const noexcept;
/** Returns the component being used for the item with the given index.
If the index is less than zero or greater than the number of items,
this will return nullptr.
@see getNumItems
*/
ToolbarItemComponent* getItemComponent (int itemIndex) const noexcept;
/** Clears this toolbar and adds to it the default set of items that the specified
factory creates.
@see ToolbarItemFactory::getDefaultItemSet
*/
void addDefaultItems (ToolbarItemFactory& factoryToUse);
//==============================================================================
/** Options for the way items should be displayed.
@see setStyle, getStyle
*/
enum ToolbarItemStyle
{
iconsOnly, /**< Means that the toolbar should just contain icons. */
iconsWithText, /**< Means that the toolbar should have text labels under each icon. */
textOnly /**< Means that the toolbar only display text labels for each item. */
};
/** Returns the toolbar's current style.
@see ToolbarItemStyle, setStyle
*/
ToolbarItemStyle getStyle() const noexcept { return toolbarStyle; }
/** Changes the toolbar's current style.
@see ToolbarItemStyle, getStyle, ToolbarItemComponent::setStyle
*/
void setStyle (const ToolbarItemStyle& newStyle);
//==============================================================================
/** Flags used by the showCustomisationDialog() method. */
enum CustomisationFlags
{
allowIconsOnlyChoice = 1, /**< If this flag is specified, the customisation dialog can
show the "icons only" option on its choice of toolbar styles. */
allowIconsWithTextChoice = 2, /**< If this flag is specified, the customisation dialog can
show the "icons with text" option on its choice of toolbar styles. */
allowTextOnlyChoice = 4, /**< If this flag is specified, the customisation dialog can
show the "text only" option on its choice of toolbar styles. */
showResetToDefaultsButton = 8, /**< If this flag is specified, the customisation dialog can
show a button to reset the toolbar to its default set of items. */
allCustomisationOptionsEnabled = (allowIconsOnlyChoice | allowIconsWithTextChoice | allowTextOnlyChoice | showResetToDefaultsButton)
};
/** Pops up a modal dialog box that allows this toolbar to be customised by the user.
The dialog contains a ToolbarItemPalette and various controls for editing other
aspects of the toolbar. The dialog box will be opened modally, but the method will
return immediately.
The factory is used to determine the set of items that will be shown on the
palette.
The optionFlags parameter is a bitwise-or of values from the CustomisationFlags
enum.
@see ToolbarItemPalette
*/
void showCustomisationDialog (ToolbarItemFactory& factory,
int optionFlags = allCustomisationOptionsEnabled);
/** Turns on or off the toolbar's editing mode, in which its items can be
rearranged by the user.
(In most cases it's easier just to use showCustomisationDialog() instead of
trying to enable editing directly).
@see ToolbarItemPalette
*/
void setEditingActive (bool editingEnabled);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the toolbar.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1003200, /**< A colour to use to fill the toolbar's background. For
more control over this, override LookAndFeel::paintToolbarBackground(). */
separatorColourId = 0x1003210, /**< A colour to use to draw the separator lines. */
buttonMouseOverBackgroundColourId = 0x1003220, /**< A colour used to paint the background of buttons when the mouse is
over them. */
buttonMouseDownBackgroundColourId = 0x1003230, /**< A colour used to paint the background of buttons when the mouse is
held down on them. */
labelTextColourId = 0x1003240, /**< A colour to use for drawing the text under buttons
when the style is set to iconsWithText or textOnly. */
editingModeOutlineColourId = 0x1003250 /**< A colour to use for an outline around buttons when
the customisation dialog is active and the mouse moves over them. */
};
//==============================================================================
/** Returns a string that represents the toolbar's current set of items.
This lets you later restore the same item layout using restoreFromString().
@see restoreFromString
*/
String toString() const;
/** Restores a set of items that was previously stored in a string by the toString()
method.
The factory object is used to create any item components that are needed.
@see toString
*/
bool restoreFromString (ToolbarItemFactory& factoryToUse,
const String& savedVersion);
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods
{
virtual ~LookAndFeelMethods() = default;
virtual void paintToolbarBackground (Graphics&, int width, int height, Toolbar&) = 0;
virtual Button* createToolbarMissingItemsButton (Toolbar&) = 0;
virtual void paintToolbarButtonBackground (Graphics&, int width, int height,
bool isMouseOver, bool isMouseDown,
ToolbarItemComponent&) = 0;
virtual void paintToolbarButtonLabel (Graphics&, int x, int y, int width, int height,
const String& text, ToolbarItemComponent&) = 0;
};
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
bool isInterestedInDragSource (const SourceDetails&) override;
/** @internal */
void itemDragMove (const SourceDetails&) override;
/** @internal */
void itemDragExit (const SourceDetails&) override;
/** @internal */
void itemDropped (const SourceDetails&) override;
/** @internal */
void lookAndFeelChanged() override;
/** @internal */
void updateAllItemPositions (bool animate);
/** @internal */
static ToolbarItemComponent* createItem (ToolbarItemFactory&, int itemId);
/** @internal */
static const char* const toolbarDragDescriptor;
private:
//==============================================================================
std::unique_ptr<Button> missingItemsButton;
bool vertical = false, isEditingActive = false;
ToolbarItemStyle toolbarStyle = iconsOnly;
class MissingItemsComponent;
friend class MissingItemsComponent;
OwnedArray<ToolbarItemComponent> items;
class Spacer;
class CustomisationDialog;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void initMissingItemButton();
void showMissingItems();
void addItemInternal (ToolbarItemFactory& factory, int itemId, int insertIndex);
ToolbarItemComponent* getNextActiveComponent (int index, int delta) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Toolbar)
};
} // namespace juce

@ -1,255 +1,255 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ToolbarItemFactory::ToolbarItemFactory() {}
ToolbarItemFactory::~ToolbarItemFactory() {}
//==============================================================================
class ToolbarItemComponent::ItemDragAndDropOverlayComponent : public Component
{
public:
ItemDragAndDropOverlayComponent()
: isDragging (false)
{
setAlwaysOnTop (true);
setRepaintsOnMouseActivity (true);
setMouseCursor (MouseCursor::DraggingHandCursor);
}
void paint (Graphics& g) override
{
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
if (isMouseOverOrDragging()
&& tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
{
g.setColour (findColour (Toolbar::editingModeOutlineColourId, true));
g.drawRect (getLocalBounds(), jmin (2, (getWidth() - 1) / 2,
(getHeight() - 1) / 2));
}
}
}
void mouseDown (const MouseEvent& e) override
{
isDragging = false;
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->dragOffsetX = e.x;
tc->dragOffsetY = e.y;
}
}
void mouseDrag (const MouseEvent& e) override
{
if (e.mouseWasDraggedSinceMouseDown() && ! isDragging)
{
isDragging = true;
if (DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this))
{
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image(), true, nullptr, &e.source);
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->isBeingDragged = true;
if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
tc->setVisible (false);
}
}
}
}
void mouseUp (const MouseEvent&) override
{
isDragging = false;
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->isBeingDragged = false;
if (Toolbar* const tb = tc->getToolbar())
tb->updateAllItemPositions (true);
else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
delete tc;
}
}
void parentSizeChanged() override
{
setBounds (0, 0, getParentWidth(), getParentHeight());
}
private:
//==============================================================================
bool isDragging;
ToolbarItemComponent* getToolbarItemComponent() const noexcept
{
return dynamic_cast<ToolbarItemComponent*> (getParentComponent());
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemDragAndDropOverlayComponent)
};
//==============================================================================
ToolbarItemComponent::ToolbarItemComponent (const int itemId_,
const String& labelText,
const bool isBeingUsedAsAButton_)
: Button (labelText),
itemId (itemId_),
mode (normalMode),
toolbarStyle (Toolbar::iconsOnly),
dragOffsetX (0),
dragOffsetY (0),
isActive (true),
isBeingDragged (false),
isBeingUsedAsAButton (isBeingUsedAsAButton_)
{
// Your item ID can't be 0!
jassert (itemId_ != 0);
}
ToolbarItemComponent::~ToolbarItemComponent()
{
overlayComp.reset();
}
Toolbar* ToolbarItemComponent::getToolbar() const
{
return dynamic_cast<Toolbar*> (getParentComponent());
}
bool ToolbarItemComponent::isToolbarVertical() const
{
const Toolbar* const t = getToolbar();
return t != nullptr && t->isVertical();
}
void ToolbarItemComponent::setStyle (const Toolbar::ToolbarItemStyle& newStyle)
{
if (toolbarStyle != newStyle)
{
toolbarStyle = newStyle;
repaint();
resized();
}
}
void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool down)
{
if (isBeingUsedAsAButton)
getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(),
over, down, *this);
if (toolbarStyle != Toolbar::iconsOnly)
{
auto indent = contentArea.getX();
auto y = indent;
auto h = getHeight() - indent * 2;
if (toolbarStyle == Toolbar::iconsWithText)
{
y = contentArea.getBottom() + indent / 2;
h -= contentArea.getHeight();
}
getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h,
getButtonText(), *this);
}
if (! contentArea.isEmpty())
{
Graphics::ScopedSaveState ss (g);
g.reduceClipRegion (contentArea);
g.setOrigin (contentArea.getPosition());
paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down);
}
}
void ToolbarItemComponent::resized()
{
if (toolbarStyle != Toolbar::textOnly)
{
const int indent = jmin (proportionOfWidth (0.08f),
proportionOfHeight (0.08f));
contentArea = Rectangle<int> (indent, indent,
getWidth() - indent * 2,
toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f)
: (getHeight() - indent * 2));
}
else
{
contentArea = {};
}
contentAreaChanged (contentArea);
}
void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode)
{
if (mode != newMode)
{
mode = newMode;
repaint();
if (mode == normalMode)
{
overlayComp.reset();
}
else if (overlayComp == nullptr)
{
overlayComp.reset (new ItemDragAndDropOverlayComponent());
addAndMakeVisible (overlayComp.get());
overlayComp->parentSizeChanged();
}
resized();
}
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ToolbarItemComponent::createAccessibilityHandler()
{
const auto shouldItemBeAccessible = (itemId != ToolbarItemFactory::separatorBarId
&& itemId != ToolbarItemFactory::spacerId
&& itemId != ToolbarItemFactory::flexibleSpacerId);
if (! shouldItemBeAccessible)
return nullptr;
return std::make_unique<ButtonAccessibilityHandler> (*this, AccessibilityRole::button);
}
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ToolbarItemFactory::ToolbarItemFactory() {}
ToolbarItemFactory::~ToolbarItemFactory() {}
//==============================================================================
class ToolbarItemComponent::ItemDragAndDropOverlayComponent : public Component
{
public:
ItemDragAndDropOverlayComponent()
: isDragging (false)
{
setAlwaysOnTop (true);
setRepaintsOnMouseActivity (true);
setMouseCursor (MouseCursor::DraggingHandCursor);
}
void paint (Graphics& g) override
{
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
if (isMouseOverOrDragging()
&& tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
{
g.setColour (findColour (Toolbar::editingModeOutlineColourId, true));
g.drawRect (getLocalBounds(), jmin (2, (getWidth() - 1) / 2,
(getHeight() - 1) / 2));
}
}
}
void mouseDown (const MouseEvent& e) override
{
isDragging = false;
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->dragOffsetX = e.x;
tc->dragOffsetY = e.y;
}
}
void mouseDrag (const MouseEvent& e) override
{
if (e.mouseWasDraggedSinceMouseDown() && ! isDragging)
{
isDragging = true;
if (DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this))
{
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), ScaledImage(), true, nullptr, &e.source);
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->isBeingDragged = true;
if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
tc->setVisible (false);
}
}
}
}
void mouseUp (const MouseEvent&) override
{
isDragging = false;
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{
tc->isBeingDragged = false;
if (Toolbar* const tb = tc->getToolbar())
tb->updateAllItemPositions (true);
else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
delete tc;
}
}
void parentSizeChanged() override
{
setBounds (0, 0, getParentWidth(), getParentHeight());
}
private:
//==============================================================================
bool isDragging;
ToolbarItemComponent* getToolbarItemComponent() const noexcept
{
return dynamic_cast<ToolbarItemComponent*> (getParentComponent());
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemDragAndDropOverlayComponent)
};
//==============================================================================
ToolbarItemComponent::ToolbarItemComponent (const int itemId_,
const String& labelText,
const bool isBeingUsedAsAButton_)
: Button (labelText),
itemId (itemId_),
mode (normalMode),
toolbarStyle (Toolbar::iconsOnly),
dragOffsetX (0),
dragOffsetY (0),
isActive (true),
isBeingDragged (false),
isBeingUsedAsAButton (isBeingUsedAsAButton_)
{
// Your item ID can't be 0!
jassert (itemId_ != 0);
}
ToolbarItemComponent::~ToolbarItemComponent()
{
overlayComp.reset();
}
Toolbar* ToolbarItemComponent::getToolbar() const
{
return dynamic_cast<Toolbar*> (getParentComponent());
}
bool ToolbarItemComponent::isToolbarVertical() const
{
const Toolbar* const t = getToolbar();
return t != nullptr && t->isVertical();
}
void ToolbarItemComponent::setStyle (const Toolbar::ToolbarItemStyle& newStyle)
{
if (toolbarStyle != newStyle)
{
toolbarStyle = newStyle;
repaint();
resized();
}
}
void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool down)
{
if (isBeingUsedAsAButton)
getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(),
over, down, *this);
if (toolbarStyle != Toolbar::iconsOnly)
{
auto indent = contentArea.getX();
auto y = indent;
auto h = getHeight() - indent * 2;
if (toolbarStyle == Toolbar::iconsWithText)
{
y = contentArea.getBottom() + indent / 2;
h -= contentArea.getHeight();
}
getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h,
getButtonText(), *this);
}
if (! contentArea.isEmpty())
{
Graphics::ScopedSaveState ss (g);
g.reduceClipRegion (contentArea);
g.setOrigin (contentArea.getPosition());
paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down);
}
}
void ToolbarItemComponent::resized()
{
if (toolbarStyle != Toolbar::textOnly)
{
const int indent = jmin (proportionOfWidth (0.08f),
proportionOfHeight (0.08f));
contentArea = Rectangle<int> (indent, indent,
getWidth() - indent * 2,
toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f)
: (getHeight() - indent * 2));
}
else
{
contentArea = {};
}
contentAreaChanged (contentArea);
}
void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode)
{
if (mode != newMode)
{
mode = newMode;
repaint();
if (mode == normalMode)
{
overlayComp.reset();
}
else if (overlayComp == nullptr)
{
overlayComp.reset (new ItemDragAndDropOverlayComponent());
addAndMakeVisible (overlayComp.get());
overlayComp->parentSizeChanged();
}
resized();
}
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ToolbarItemComponent::createAccessibilityHandler()
{
const auto shouldItemBeAccessible = (itemId != ToolbarItemFactory::separatorBarId
&& itemId != ToolbarItemFactory::spacerId
&& itemId != ToolbarItemFactory::flexibleSpacerId);
if (! shouldItemBeAccessible)
return createIgnoredAccessibilityHandler (*this);
return std::make_unique<ButtonAccessibilityHandler> (*this, AccessibilityRole::button);
}
} // namespace juce

@ -1,209 +1,209 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that can be used as one of the items in a Toolbar.
Each of the items on a toolbar must be a component derived from ToolbarItemComponent,
and these objects are always created by a ToolbarItemFactory - see the ToolbarItemFactory
class for further info about creating them.
The ToolbarItemComponent class is actually a button, but can be used to hold non-button
components too. To do this, set the value of isBeingUsedAsAButton to false when
calling the constructor, and override contentAreaChanged(), in which you can position
any sub-components you need to add.
To add basic buttons without writing a special subclass, have a look at the
ToolbarButton class.
@see ToolbarButton, Toolbar, ToolbarItemFactory
@tags{GUI}
*/
class JUCE_API ToolbarItemComponent : public Button
{
public:
//==============================================================================
/** Constructor.
@param itemId the ID of the type of toolbar item which this represents
@param labelText the text to display if the toolbar's style is set to
Toolbar::iconsWithText or Toolbar::textOnly
@param isBeingUsedAsAButton set this to false if you don't want the button
to draw itself with button over/down states when the mouse
moves over it or clicks
*/
ToolbarItemComponent (int itemId,
const String& labelText,
bool isBeingUsedAsAButton);
/** Destructor. */
~ToolbarItemComponent() override;
//==============================================================================
/** Returns the item type ID that this component represents.
This value is in the constructor.
*/
int getItemId() const noexcept { return itemId; }
/** Returns the toolbar that contains this component, or nullptr if it's not currently
inside one.
*/
Toolbar* getToolbar() const;
/** Returns true if this component is currently inside a toolbar which is vertical.
@see Toolbar::isVertical
*/
bool isToolbarVertical() const;
/** Returns the current style setting of this item.
Styles are listed in the Toolbar::ToolbarItemStyle enum.
@see setStyle, Toolbar::getStyle
*/
Toolbar::ToolbarItemStyle getStyle() const noexcept { return toolbarStyle; }
/** Changes the current style setting of this item.
Styles are listed in the Toolbar::ToolbarItemStyle enum, and are automatically updated
by the toolbar that holds this item.
@see setStyle, Toolbar::setStyle
*/
virtual void setStyle (const Toolbar::ToolbarItemStyle& newStyle);
/** Returns the area of the component that should be used to display the button image or
other contents of the item.
This content area may change when the item's style changes, and may leave a space around the
edge of the component where the text label can be shown.
@see contentAreaChanged
*/
Rectangle<int> getContentArea() const noexcept { return contentArea; }
//==============================================================================
/** This method must return the size criteria for this item, based on a given toolbar
size and orientation.
The preferredSize, minSize and maxSize values must all be set by your implementation
method. If the toolbar is horizontal, these will be the width of the item; for a vertical
toolbar, they refer to the item's height.
The preferredSize is the size that the component would like to be, and this must be
between the min and max sizes. For a fixed-size item, simply set all three variables to
the same value.
The toolbarThickness parameter tells you the depth of the toolbar - the same as calling
Toolbar::getThickness().
The isToolbarVertical parameter tells you whether the bar is oriented horizontally or
vertically.
*/
virtual bool getToolbarItemSizes (int toolbarThickness,
bool isToolbarVertical,
int& preferredSize,
int& minSize,
int& maxSize) = 0;
/** Your subclass should use this method to draw its content area.
The graphics object that is passed-in will have been clipped and had its origin
moved to fit the content area as specified get getContentArea(). The width and height
parameters are the width and height of the content area.
If the component you're writing isn't a button, you can just do nothing in this method.
*/
virtual void paintButtonArea (Graphics& g,
int width, int height,
bool isMouseOver, bool isMouseDown) = 0;
/** Callback to indicate that the content area of this item has changed.
This might be because the component was resized, or because the style changed and
the space needed for the text label is different.
See getContentArea() for a description of what the area is.
*/
virtual void contentAreaChanged (const Rectangle<int>& newBounds) = 0;
//==============================================================================
/** Editing modes.
These are used by setEditingMode(), but will be rarely needed in user code.
*/
enum ToolbarEditingMode
{
normalMode = 0, /**< Means that the component is active, inside a toolbar. */
editableOnToolbar, /**< Means that the component is on a toolbar, but the toolbar is in
customisation mode, and the items can be dragged around. */
editableOnPalette /**< Means that the component is on an new-item palette, so it can be
dragged onto a toolbar to add it to that bar.*/
};
/** Changes the editing mode of this component.
This is used by the ToolbarItemPalette and related classes for making the items draggable,
and is unlikely to be of much use in end-user-code.
*/
void setEditingMode (const ToolbarEditingMode newMode);
/** Returns the current editing mode of this component.
This is used by the ToolbarItemPalette and related classes for making the items draggable,
and is unlikely to be of much use in end-user-code.
*/
ToolbarEditingMode getEditingMode() const noexcept { return mode; }
//==============================================================================
/** @internal */
void paintButton (Graphics&, bool isMouseOver, bool isMouseDown) override;
/** @internal */
void resized() override;
private:
friend class Toolbar;
class ItemDragAndDropOverlayComponent;
friend class ItemDragAndDropOverlayComponent;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
const int itemId;
ToolbarEditingMode mode;
Toolbar::ToolbarItemStyle toolbarStyle;
std::unique_ptr<Component> overlayComp;
int dragOffsetX, dragOffsetY;
bool isActive, isBeingDragged, isBeingUsedAsAButton;
Rectangle<int> contentArea;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToolbarItemComponent)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component that can be used as one of the items in a Toolbar.
Each of the items on a toolbar must be a component derived from ToolbarItemComponent,
and these objects are always created by a ToolbarItemFactory - see the ToolbarItemFactory
class for further info about creating them.
The ToolbarItemComponent class is actually a button, but can be used to hold non-button
components too. To do this, set the value of isBeingUsedAsAButton to false when
calling the constructor, and override contentAreaChanged(), in which you can position
any sub-components you need to add.
To add basic buttons without writing a special subclass, have a look at the
ToolbarButton class.
@see ToolbarButton, Toolbar, ToolbarItemFactory
@tags{GUI}
*/
class JUCE_API ToolbarItemComponent : public Button
{
public:
//==============================================================================
/** Constructor.
@param itemId the ID of the type of toolbar item which this represents
@param labelText the text to display if the toolbar's style is set to
Toolbar::iconsWithText or Toolbar::textOnly
@param isBeingUsedAsAButton set this to false if you don't want the button
to draw itself with button over/down states when the mouse
moves over it or clicks
*/
ToolbarItemComponent (int itemId,
const String& labelText,
bool isBeingUsedAsAButton);
/** Destructor. */
~ToolbarItemComponent() override;
//==============================================================================
/** Returns the item type ID that this component represents.
This value is in the constructor.
*/
int getItemId() const noexcept { return itemId; }
/** Returns the toolbar that contains this component, or nullptr if it's not currently
inside one.
*/
Toolbar* getToolbar() const;
/** Returns true if this component is currently inside a toolbar which is vertical.
@see Toolbar::isVertical
*/
bool isToolbarVertical() const;
/** Returns the current style setting of this item.
Styles are listed in the Toolbar::ToolbarItemStyle enum.
@see setStyle, Toolbar::getStyle
*/
Toolbar::ToolbarItemStyle getStyle() const noexcept { return toolbarStyle; }
/** Changes the current style setting of this item.
Styles are listed in the Toolbar::ToolbarItemStyle enum, and are automatically updated
by the toolbar that holds this item.
@see setStyle, Toolbar::setStyle
*/
virtual void setStyle (const Toolbar::ToolbarItemStyle& newStyle);
/** Returns the area of the component that should be used to display the button image or
other contents of the item.
This content area may change when the item's style changes, and may leave a space around the
edge of the component where the text label can be shown.
@see contentAreaChanged
*/
Rectangle<int> getContentArea() const noexcept { return contentArea; }
//==============================================================================
/** This method must return the size criteria for this item, based on a given toolbar
size and orientation.
The preferredSize, minSize and maxSize values must all be set by your implementation
method. If the toolbar is horizontal, these will be the width of the item; for a vertical
toolbar, they refer to the item's height.
The preferredSize is the size that the component would like to be, and this must be
between the min and max sizes. For a fixed-size item, simply set all three variables to
the same value.
The toolbarThickness parameter tells you the depth of the toolbar - the same as calling
Toolbar::getThickness().
The isToolbarVertical parameter tells you whether the bar is oriented horizontally or
vertically.
*/
virtual bool getToolbarItemSizes (int toolbarThickness,
bool isToolbarVertical,
int& preferredSize,
int& minSize,
int& maxSize) = 0;
/** Your subclass should use this method to draw its content area.
The graphics object that is passed-in will have been clipped and had its origin
moved to fit the content area as specified get getContentArea(). The width and height
parameters are the width and height of the content area.
If the component you're writing isn't a button, you can just do nothing in this method.
*/
virtual void paintButtonArea (Graphics& g,
int width, int height,
bool isMouseOver, bool isMouseDown) = 0;
/** Callback to indicate that the content area of this item has changed.
This might be because the component was resized, or because the style changed and
the space needed for the text label is different.
See getContentArea() for a description of what the area is.
*/
virtual void contentAreaChanged (const Rectangle<int>& newBounds) = 0;
//==============================================================================
/** Editing modes.
These are used by setEditingMode(), but will be rarely needed in user code.
*/
enum ToolbarEditingMode
{
normalMode = 0, /**< Means that the component is active, inside a toolbar. */
editableOnToolbar, /**< Means that the component is on a toolbar, but the toolbar is in
customisation mode, and the items can be dragged around. */
editableOnPalette /**< Means that the component is on an new-item palette, so it can be
dragged onto a toolbar to add it to that bar.*/
};
/** Changes the editing mode of this component.
This is used by the ToolbarItemPalette and related classes for making the items draggable,
and is unlikely to be of much use in end-user-code.
*/
void setEditingMode (const ToolbarEditingMode newMode);
/** Returns the current editing mode of this component.
This is used by the ToolbarItemPalette and related classes for making the items draggable,
and is unlikely to be of much use in end-user-code.
*/
ToolbarEditingMode getEditingMode() const noexcept { return mode; }
//==============================================================================
/** @internal */
void paintButton (Graphics&, bool isMouseOver, bool isMouseDown) override;
/** @internal */
void resized() override;
private:
friend class Toolbar;
class ItemDragAndDropOverlayComponent;
friend class ItemDragAndDropOverlayComponent;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
const int itemId;
ToolbarEditingMode mode;
Toolbar::ToolbarItemStyle toolbarStyle;
std::unique_ptr<Component> overlayComp;
int dragOffsetX, dragOffsetY;
bool isActive, isBeingDragged, isBeingUsedAsAButton;
Rectangle<int> contentArea;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToolbarItemComponent)
};
} // namespace juce

@ -1,109 +1,109 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A factory object which can create ToolbarItemComponent objects.
A subclass of ToolbarItemFactory publishes a set of types of toolbar item
that it can create.
Each type of item is identified by a unique ID, and multiple instances of an
item type can exist at once (even on the same toolbar, e.g. spacers or separator
bars).
@see Toolbar, ToolbarItemComponent, ToolbarButton
@tags{GUI}
*/
class JUCE_API ToolbarItemFactory
{
public:
//==============================================================================
ToolbarItemFactory();
/** Destructor. */
virtual ~ToolbarItemFactory();
//==============================================================================
/** A set of reserved item ID values, used for the built-in item types.
*/
enum SpecialItemIds
{
separatorBarId = -1, /**< The item ID for a vertical (or horizontal) separator bar that
can be placed between sets of items to break them into groups. */
spacerId = -2, /**< The item ID for a fixed-width space that can be placed between
items.*/
flexibleSpacerId = -3 /**< The item ID for a gap that pushes outwards against the things on
either side of it, filling any available space. */
};
//==============================================================================
/** Must return a list of the IDs for all the item types that this factory can create.
The ids should be added to the array that is passed-in.
An item ID can be any integer you choose, except for 0, which is considered a null ID,
and the predefined IDs in the SpecialItemIds enum.
You should also add the built-in types (separatorBarId, spacerId and flexibleSpacerId)
to this list if you want your toolbar to be able to contain those items.
The list returned here is used by the ToolbarItemPalette class to obtain its list
of available items, and their order on the palette will reflect the order in which
they appear on this list.
@see ToolbarItemPalette
*/
virtual void getAllToolbarItemIds (Array <int>& ids) = 0;
/** Must return the set of items that should be added to a toolbar as its default set.
This method is used by Toolbar::addDefaultItems() to determine which items to
create.
The items that your method adds to the array that is passed-in will be added to the
toolbar in the same order. Items can appear in the list more than once.
*/
virtual void getDefaultItemSet (Array <int>& ids) = 0;
/** Must create an instance of one of the items that the factory lists in its
getAllToolbarItemIds() method.
The itemId parameter can be any of the values listed by your getAllToolbarItemIds()
method, except for the built-in item types from the SpecialItemIds enum, which
are created internally by the toolbar code.
Try not to keep a pointer to the object that is returned, as it will be deleted
automatically by the toolbar, and remember that multiple instances of the same
item type are likely to exist at the same time.
*/
virtual ToolbarItemComponent* createItem (int itemId) = 0;
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A factory object which can create ToolbarItemComponent objects.
A subclass of ToolbarItemFactory publishes a set of types of toolbar item
that it can create.
Each type of item is identified by a unique ID, and multiple instances of an
item type can exist at once (even on the same toolbar, e.g. spacers or separator
bars).
@see Toolbar, ToolbarItemComponent, ToolbarButton
@tags{GUI}
*/
class JUCE_API ToolbarItemFactory
{
public:
//==============================================================================
ToolbarItemFactory();
/** Destructor. */
virtual ~ToolbarItemFactory();
//==============================================================================
/** A set of reserved item ID values, used for the built-in item types.
*/
enum SpecialItemIds
{
separatorBarId = -1, /**< The item ID for a vertical (or horizontal) separator bar that
can be placed between sets of items to break them into groups. */
spacerId = -2, /**< The item ID for a fixed-width space that can be placed between
items.*/
flexibleSpacerId = -3 /**< The item ID for a gap that pushes outwards against the things on
either side of it, filling any available space. */
};
//==============================================================================
/** Must return a list of the IDs for all the item types that this factory can create.
The ids should be added to the array that is passed-in.
An item ID can be any integer you choose, except for 0, which is considered a null ID,
and the predefined IDs in the SpecialItemIds enum.
You should also add the built-in types (separatorBarId, spacerId and flexibleSpacerId)
to this list if you want your toolbar to be able to contain those items.
The list returned here is used by the ToolbarItemPalette class to obtain its list
of available items, and their order on the palette will reflect the order in which
they appear on this list.
@see ToolbarItemPalette
*/
virtual void getAllToolbarItemIds (Array <int>& ids) = 0;
/** Must return the set of items that should be added to a toolbar as its default set.
This method is used by Toolbar::addDefaultItems() to determine which items to
create.
The items that your method adds to the array that is passed-in will be added to the
toolbar in the same order. Items can appear in the list more than once.
*/
virtual void getDefaultItemSet (Array <int>& ids) = 0;
/** Must create an instance of one of the items that the factory lists in its
getAllToolbarItemIds() method.
The itemId parameter can be any of the values listed by your getAllToolbarItemIds()
method, except for the built-in item types from the SpecialItemIds enum, which
are created internally by the toolbar code.
Try not to keep a pointer to the object that is returned, as it will be deleted
automatically by the toolbar, and remember that multiple instances of the same
item type are likely to exist at the same time.
*/
virtual ToolbarItemComponent* createItem (int itemId) = 0;
};
} // namespace juce

@ -1,116 +1,116 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ToolbarItemPalette::ToolbarItemPalette (ToolbarItemFactory& tbf, Toolbar& bar)
: factory (tbf), toolbar (bar)
{
auto* itemHolder = new Component();
viewport.setViewedComponent (itemHolder);
Array<int> allIds;
factory.getAllToolbarItemIds (allIds);
for (auto& i : allIds)
addComponent (i, -1);
addAndMakeVisible (viewport);
}
ToolbarItemPalette::~ToolbarItemPalette()
{
}
//==============================================================================
void ToolbarItemPalette::addComponent (const int itemId, const int index)
{
if (auto* tc = Toolbar::createItem (factory, itemId))
{
items.insert (index, tc);
viewport.getViewedComponent()->addAndMakeVisible (tc, index);
tc->setEditingMode (ToolbarItemComponent::editableOnPalette);
}
else
{
jassertfalse;
}
}
void ToolbarItemPalette::replaceComponent (ToolbarItemComponent& comp)
{
auto index = items.indexOf (&comp);
jassert (index >= 0);
items.removeObject (&comp, false);
addComponent (comp.getItemId(), index);
resized();
}
void ToolbarItemPalette::resized()
{
viewport.setBoundsInset (BorderSize<int> (1));
auto* itemHolder = viewport.getViewedComponent();
const int indent = 8;
const int preferredWidth = viewport.getWidth() - viewport.getScrollBarThickness() - indent;
const int height = toolbar.getThickness();
auto x = indent;
auto y = indent;
int maxX = 0;
for (auto* tc : items)
{
tc->setStyle (toolbar.getStyle());
int preferredSize = 1, minSize = 1, maxSize = 1;
if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize))
{
if (x + preferredSize > preferredWidth && x > indent)
{
x = indent;
y += height;
}
tc->setBounds (x, y, preferredSize, height);
x += preferredSize + 8;
maxX = jmax (maxX, x);
}
}
itemHolder->setSize (maxX, y + height + 8);
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ToolbarItemPalette::createAccessibilityHandler()
{
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
}
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
ToolbarItemPalette::ToolbarItemPalette (ToolbarItemFactory& tbf, Toolbar& bar)
: factory (tbf), toolbar (bar)
{
auto* itemHolder = new Component();
viewport.setViewedComponent (itemHolder);
Array<int> allIds;
factory.getAllToolbarItemIds (allIds);
for (auto& i : allIds)
addComponent (i, -1);
addAndMakeVisible (viewport);
}
ToolbarItemPalette::~ToolbarItemPalette()
{
}
//==============================================================================
void ToolbarItemPalette::addComponent (const int itemId, const int index)
{
if (auto* tc = Toolbar::createItem (factory, itemId))
{
items.insert (index, tc);
viewport.getViewedComponent()->addAndMakeVisible (tc, index);
tc->setEditingMode (ToolbarItemComponent::editableOnPalette);
}
else
{
jassertfalse;
}
}
void ToolbarItemPalette::replaceComponent (ToolbarItemComponent& comp)
{
auto index = items.indexOf (&comp);
jassert (index >= 0);
items.removeObject (&comp, false);
addComponent (comp.getItemId(), index);
resized();
}
void ToolbarItemPalette::resized()
{
viewport.setBoundsInset (BorderSize<int> (1));
auto* itemHolder = viewport.getViewedComponent();
const int indent = 8;
const int preferredWidth = viewport.getWidth() - viewport.getScrollBarThickness() - indent;
const int height = toolbar.getThickness();
auto x = indent;
auto y = indent;
int maxX = 0;
for (auto* tc : items)
{
tc->setStyle (toolbar.getStyle());
int preferredSize = 1, minSize = 1, maxSize = 1;
if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize))
{
if (x + preferredSize > preferredWidth && x > indent)
{
x = indent;
y += height;
}
tc->setBounds (x, y, preferredSize, height);
x += preferredSize + 8;
maxX = jmax (maxX, x);
}
}
itemHolder->setSize (maxX, y + height + 8);
}
//==============================================================================
std::unique_ptr<AccessibilityHandler> ToolbarItemPalette::createAccessibilityHandler()
{
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
}
} // namespace juce

@ -1,78 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component containing a list of toolbar items, which the user can drag onto
a toolbar to add them.
You can use this class directly, but it's a lot easier to call Toolbar::showCustomisationDialog(),
which automatically shows one of these in a dialog box with lots of extra controls.
@see Toolbar
@tags{GUI}
*/
class JUCE_API ToolbarItemPalette : public Component,
public DragAndDropContainer
{
public:
//==============================================================================
/** Creates a palette of items for a given factory, with the aim of adding them
to the specified toolbar.
The ToolbarItemFactory::getAllToolbarItemIds() method is used to create the
set of items that are shown in this palette.
The toolbar and factory must not be deleted while this object exists.
*/
ToolbarItemPalette (ToolbarItemFactory& factory,
Toolbar& toolbar);
/** Destructor. */
~ToolbarItemPalette() override;
//==============================================================================
/** @internal */
void resized() override;
private:
ToolbarItemFactory& factory;
Toolbar& toolbar;
Viewport viewport;
OwnedArray<ToolbarItemComponent> items;
friend class Toolbar;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void replaceComponent (ToolbarItemComponent&);
void addComponent (int itemId, int index);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToolbarItemPalette)
};
} // namespace juce
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A component containing a list of toolbar items, which the user can drag onto
a toolbar to add them.
You can use this class directly, but it's a lot easier to call Toolbar::showCustomisationDialog(),
which automatically shows one of these in a dialog box with lots of extra controls.
@see Toolbar
@tags{GUI}
*/
class JUCE_API ToolbarItemPalette : public Component,
public DragAndDropContainer
{
public:
//==============================================================================
/** Creates a palette of items for a given factory, with the aim of adding them
to the specified toolbar.
The ToolbarItemFactory::getAllToolbarItemIds() method is used to create the
set of items that are shown in this palette.
The toolbar and factory must not be deleted while this object exists.
*/
ToolbarItemPalette (ToolbarItemFactory& factory,
Toolbar& toolbar);
/** Destructor. */
~ToolbarItemPalette() override;
//==============================================================================
/** @internal */
void resized() override;
private:
ToolbarItemFactory& factory;
Toolbar& toolbar;
Viewport viewport;
OwnedArray<ToolbarItemComponent> items;
friend class Toolbar;
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
void replaceComponent (ToolbarItemComponent&);
void addComponent (int itemId, int index);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToolbarItemPalette)
};
} // namespace juce

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff