Skip to content

Commit 6217fdd

Browse files
committed
Implemented TiledButtonGroupManager.
* This class position buttons inside itself as tiles and has feature which gives us fuzzy button selection possibility via mouse drag (or SHIFT+mouse drag for deselection).
1 parent 37d28e2 commit 6217fdd

3 files changed

Lines changed: 290 additions & 1 deletion

File tree

Source/UI/Utils/ButtonGroupManager.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ void ButtonGroupManager::addButton (Button* newButton)
9191

9292
if (m_isRadioButtonMode)
9393
{
94-
newButton->setClickingTogglesState (true);
9594
newButton->setRadioGroupId (1);
9695
}
9796

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
------------------------------------------------------------------
3+
4+
This file is part of the Open Ephys GUI
5+
Copyright (C) 2016 Open Ephys
6+
7+
------------------------------------------------------------------
8+
9+
This program is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
*/
23+
24+
#include "TiledButtonGroupManager.h"
25+
#include "../MaterialButtonLookAndFeel.h"
26+
27+
#include <algorithm>
28+
29+
30+
TiledButtonGroupManager::TiledButtonGroupManager()
31+
: m_firstSelectedButtonIdx (-1)
32+
, m_lastSelectedButtonIdx (-1)
33+
, m_isToggleOnMode (true)
34+
, m_isDraggingMouseNow (false)
35+
, m_isSelectButtonsByDragging (false)
36+
, m_buttonWidth (0)
37+
, m_buttonHeight (0)
38+
{
39+
setRadioButtonMode (false);
40+
setButtonsLookAndFeel (new MaterialButtonLookAndFeel);
41+
}
42+
43+
44+
void TiledButtonGroupManager::resized()
45+
{
46+
const int width = getWidth();
47+
48+
if (! width)
49+
return;
50+
51+
const int minPadding = 5;
52+
const int numButtonsInTheRow = width / (m_buttonWidth + minPadding);
53+
const int padding = jmax (minPadding, (width - numButtonsInTheRow * m_buttonWidth) / (numButtonsInTheRow - 1));
54+
55+
juce::Rectangle<int> buttonBounds (0, 0, m_buttonWidth, m_buttonHeight);
56+
const int numButtons = m_buttons.size();
57+
for (int i = 0; i < numButtons; ++i)
58+
{
59+
m_buttons[i]->setBounds (buttonBounds);
60+
61+
// Go to the next row
62+
if ( (i + 1) % numButtonsInTheRow == 0)
63+
{
64+
buttonBounds.setX (0);
65+
buttonBounds.translate (0, m_buttonHeight + padding);
66+
}
67+
// Go to the next column
68+
else
69+
{
70+
buttonBounds.translate (m_buttonWidth + padding, 0);
71+
}
72+
}
73+
}
74+
75+
76+
void TiledButtonGroupManager::mouseDown (const MouseEvent& e)
77+
{
78+
}
79+
80+
81+
void TiledButtonGroupManager::mouseUp (const MouseEvent& e)
82+
{
83+
m_isDraggingMouseNow = false;
84+
85+
m_firstSelectedButtonIdx = -1;
86+
m_lastSelectedButtonIdx = -1;
87+
}
88+
89+
90+
void TiledButtonGroupManager::mouseDrag (const MouseEvent& e)
91+
{
92+
if (! m_isSelectButtonsByDragging)
93+
return;
94+
95+
m_isDraggingMouseNow = true;
96+
97+
// Is shift + drag mouse action occurs, then we should toggle on buttons;
98+
// Otherwise - toggle off.
99+
m_isToggleOnMode = ! e.mods.isShiftDown();
100+
101+
const int currentButtonIdx = getIndexOfButtonAtPosition (e.getEventRelativeTo (this).getPosition());
102+
103+
// Remember the first button on which we started dragging
104+
if (m_firstSelectedButtonIdx == -1
105+
&& m_lastSelectedButtonIdx == -1
106+
&& currentButtonIdx >= 0)
107+
{
108+
m_firstSelectedButtonIdx = currentButtonIdx;
109+
}
110+
111+
112+
if (currentButtonIdx != -1
113+
&& currentButtonIdx != m_lastSelectedButtonIdx)
114+
{
115+
m_lastSelectedButtonIdx = currentButtonIdx;
116+
117+
// Get the indices of range which we should to select (get FROM index and TO index)
118+
const int fromIndex = jmin (m_firstSelectedButtonIdx, m_lastSelectedButtonIdx);
119+
const int toIndex = jmax (m_firstSelectedButtonIdx, m_lastSelectedButtonIdx);
120+
121+
for (int i = fromIndex; i <= toIndex; ++i)
122+
{
123+
// Trigger click only if the button still isn't selected/deselected (according to the SHIFT holds)
124+
if (m_buttons[i]->getToggleState() != m_isToggleOnMode)
125+
// Trigger click in the button, this will call buttonClicked() method, where we will
126+
m_buttons[i]->triggerClick();
127+
}
128+
}
129+
}
130+
131+
132+
void TiledButtonGroupManager::buttonClicked (Button* buttonThatWasClicked)
133+
{
134+
// Fast selection enabled and we dragging mouse now to select
135+
if (m_isSelectButtonsByDragging
136+
&& m_isDraggingMouseNow)
137+
{
138+
buttonThatWasClicked->setToggleState (m_isToggleOnMode, dontSendNotification);
139+
}
140+
// Default selection
141+
else
142+
{
143+
buttonThatWasClicked->setToggleState (! buttonThatWasClicked->getToggleState(), dontSendNotification);
144+
}
145+
146+
// Notify the listener
147+
ButtonGroupManager::buttonClicked (buttonThatWasClicked);
148+
}
149+
150+
151+
void TiledButtonGroupManager::addButton (Button* newButton)
152+
{
153+
ButtonGroupManager::addButton (newButton);
154+
155+
// Disable default clicking on button
156+
newButton->addMouseListener (this, false);
157+
}
158+
159+
160+
int TiledButtonGroupManager::getIndexOfButtonAtPosition (Point<int> position)
161+
{
162+
const int numButtons = m_buttons.size();
163+
for (int i = 0; i < numButtons; ++i)
164+
{
165+
if (m_buttons[i]->getBounds().contains (position))
166+
return i;
167+
}
168+
169+
return -1;
170+
}
171+
172+
173+
bool TiledButtonGroupManager::isFastSelectionModeEnabled()
174+
{
175+
return m_isSelectButtonsByDragging;
176+
}
177+
178+
179+
void TiledButtonGroupManager::setFastSelectionModeEnabled (bool isFastSelectionMode)
180+
{
181+
m_isSelectButtonsByDragging = isFastSelectionMode;
182+
}
183+
184+
185+
void TiledButtonGroupManager::setButtonSize (int buttonWidth, int buttonHeight)
186+
{
187+
m_buttonWidth = buttonWidth;
188+
m_buttonHeight = buttonHeight;
189+
190+
std::for_each (m_buttons.begin(), m_buttons.end(),
191+
[=] (Button* button) { button->setSize (buttonWidth, buttonHeight); });
192+
193+
resized();
194+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
------------------------------------------------------------------
3+
4+
This file is part of the Open Ephys GUI
5+
Copyright (C) 2016 Open Ephys
6+
7+
------------------------------------------------------------------
8+
9+
This program is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+
*/
23+
24+
#ifndef TILEDBUTTONGROUPMANAGER_H_INCLUDED
25+
#define TILEDBUTTONGROUPMANAGER_H_INCLUDED
26+
27+
#include "../../../JuceLibraryCode/JuceHeader.h"
28+
#include "../../Processors/PluginManager/OpenEphysPlugin.h"
29+
#include "ButtonGroupManager.h"
30+
31+
32+
/**
33+
34+
This class provides possibility to store buttons in several rows having tile-structure.
35+
It is responsible for positioning of buttons, any animations during resizing.
36+
It also have "Fast select" feature which allows as to quickly select many buttons
37+
using mouse drag selection. (mouse drag - to select, shift+mouse drag to deselect)
38+
39+
*/
40+
41+
42+
class PLUGIN_API TiledButtonGroupManager : public ButtonGroupManager
43+
{
44+
public:
45+
TiledButtonGroupManager();
46+
47+
// Component methods
48+
// ===========================================================
49+
void resized() override;
50+
51+
void mouseDown (const MouseEvent& e) override;
52+
void mouseUp (const MouseEvent& e) override;
53+
void mouseDrag (const MouseEvent& e) override;
54+
// ===========================================================
55+
56+
// Button::Listener methods
57+
// ===========================================================
58+
void buttonClicked (Button* buttonThatWasClicked);
59+
60+
/** Returns whether fast selection mode (toggle on or off buttons by dragging mouse) is enabled or not */
61+
bool isFastSelectionModeEnabled();
62+
63+
/** Sets whether fast selection mode (toggle on or off buttons by dragging mouse) will be enabled */
64+
void setFastSelectionModeEnabled (bool isFastSelectionMode);
65+
66+
/** Sets the size of each button */
67+
void setButtonSize (int buttonWidth, int buttonHeight);
68+
69+
/** Add button to the array of buttons to manage it.
70+
71+
This class controls ownership of buttons.
72+
*/
73+
void addButton (Button* newButton);
74+
75+
76+
private:
77+
// Returns the index of button at given position.
78+
// If nothing found at this position - returns -1.
79+
int getIndexOfButtonAtPosition (Point<int> position);
80+
81+
int m_buttonWidth;
82+
int m_buttonHeight;
83+
84+
int m_firstSelectedButtonIdx;
85+
int m_lastSelectedButtonIdx;
86+
bool m_isToggleOnMode;
87+
bool m_isDraggingMouseNow;
88+
bool m_isSelectButtonsByDragging;
89+
90+
// ===========================================================
91+
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TiledButtonGroupManager)
92+
};
93+
94+
95+
96+
#endif //TILEDBUTTONGROUPMANAGER_H_INCLUDED

0 commit comments

Comments
 (0)