Browse Source

added methods for setting the explicit order in which components have their focus traversed, and added jucer support for setting this value

tags/2021-05-28
jules 18 years ago
parent
commit
3958257f40
10 changed files with 169 additions and 31 deletions
  1. +61
    -1
      extras/the jucer/src/model/components/jucer_ComponentTypeHandler.cpp
  2. +2
    -2
      src/juce_appframework/gui/components/controls/juce_ListBox.cpp
  3. +1
    -1
      src/juce_appframework/gui/components/controls/juce_TableHeaderComponent.cpp
  4. +10
    -0
      src/juce_appframework/gui/components/juce_Component.cpp
  5. +58
    -11
      src/juce_appframework/gui/components/juce_Component.h
  6. +19
    -8
      src/juce_appframework/gui/components/keyboard/juce_KeyboardFocusTraverser.cpp
  7. +15
    -5
      src/juce_appframework/gui/components/keyboard/juce_KeyboardFocusTraverser.h
  8. +1
    -1
      src/juce_appframework/gui/graphics/fonts/juce_GlyphArrangement.cpp
  9. +1
    -1
      src/juce_appframework/gui/graphics/fonts/juce_Typeface.cpp
  10. +1
    -1
      src/juce_core/text/juce_XmlElement.cpp

+ 61
- 1
extras/the jucer/src/model/components/jucer_ComponentTypeHandler.cpp View File

@@ -154,6 +154,7 @@ XmlElement* ComponentTypeHandler::createXmlFor (Component* comp, const Component
e->setAttribute (T("id"), String::toHexString (getComponentId (comp))); e->setAttribute (T("id"), String::toHexString (getComponentId (comp)));
e->setAttribute (T("memberName"), comp->getComponentProperty (T("memberName"), false)); e->setAttribute (T("memberName"), comp->getComponentProperty (T("memberName"), false));
e->setAttribute (T("virtualName"), comp->getComponentProperty (T("virtualName"), false)); e->setAttribute (T("virtualName"), comp->getComponentProperty (T("virtualName"), false));
e->setAttribute (T("explicitFocusOrder"), comp->getExplicitFocusOrder());
RelativePositionedRectangle pos (getComponentPosition (comp)); RelativePositionedRectangle pos (getComponentPosition (comp));
pos.updateFromComponent (*comp, layout); pos.updateFromComponent (*comp, layout);
@@ -188,6 +189,7 @@ bool ComponentTypeHandler::restoreFromXml (const XmlElement& xml,
setComponentId (comp, xml.getStringAttribute (T("id")).getHexValue64()); setComponentId (comp, xml.getStringAttribute (T("id")).getHexValue64());
comp->setComponentProperty (T("memberName"), xml.getStringAttribute (T("memberName"))); comp->setComponentProperty (T("memberName"), xml.getStringAttribute (T("memberName")));
comp->setComponentProperty (T("virtualName"), xml.getStringAttribute (T("virtualName"))); comp->setComponentProperty (T("virtualName"), xml.getStringAttribute (T("virtualName")));
comp->setExplicitFocusOrder (xml.getIntAttribute (T("explicitFocusOrder")));
RelativePositionedRectangle currentPos (getComponentPosition (comp)); RelativePositionedRectangle currentPos (getComponentPosition (comp));
currentPos.updateFromComponent (*comp, layout); currentPos.updateFromComponent (*comp, layout);
@@ -330,7 +332,6 @@ private:
String newValue, oldValue; String newValue, oldValue;
}; };
}; };
//============================================================================== //==============================================================================
@@ -370,6 +371,58 @@ private:
JucerDocument& document; JucerDocument& document;
}; };
//==============================================================================
class FocusOrderProperty : public ComponentTextProperty <Component>
{
public:
FocusOrderProperty (Component* comp, JucerDocument& document)
: ComponentTextProperty <Component> (T("focus order"), 8, false, comp, document)
{
}
const String getText() const
{
return String (component->getExplicitFocusOrder());
}
void setText (const String& newText)
{
document.perform (new SetFocusOrderAction (component, *document.getComponentLayout(), newText.getIntValue()),
T("Change focus order"));
}
private:
class SetFocusOrderAction : public ComponentUndoableAction <Component>
{
public:
SetFocusOrderAction (Component* const comp, ComponentLayout& layout, const int newOrder_)
: ComponentUndoableAction <Component> (comp, layout),
newValue (newOrder_)
{
oldValue = comp->getExplicitFocusOrder();
}
bool perform()
{
showCorrectTab();
getComponent()->setExplicitFocusOrder (newValue);
changed();
return true;
}
bool undo()
{
showCorrectTab();
getComponent()->setExplicitFocusOrder (oldValue);
changed();
return true;
}
int newValue, oldValue;
};
};
//============================================================================== //==============================================================================
void ComponentTypeHandler::getEditableProperties (Component* component, void ComponentTypeHandler::getEditableProperties (Component* component,
JucerDocument& document, JucerDocument& document,
@@ -386,6 +439,8 @@ void ComponentTypeHandler::getEditableProperties (Component* component,
if (dynamic_cast <SettableTooltipClient*> (component) != 0) if (dynamic_cast <SettableTooltipClient*> (component) != 0)
properties.add (new TooltipProperty (component, document)); properties.add (new TooltipProperty (component, document));
properties.add (new FocusOrderProperty (component, document));
} }
void ComponentTypeHandler::addPropertiesToPropertyPanel (Component* comp, void ComponentTypeHandler::addPropertiesToPropertyPanel (Component* comp,
@@ -531,6 +586,11 @@ void ComponentTypeHandler::fillInCreationCode (GeneratedCode& code, Component* c
<< ");\n"; << ");\n";
} }
if (component->getExplicitFocusOrder() > 0)
s << memberVariableName << "->setExplicitFocusOrder ("
<< component->getExplicitFocusOrder()
<< ");\n";
code.constructorCode += s; code.constructorCode += s;
} }


+ 2
- 2
src/juce_appframework/gui/components/controls/juce_ListBox.cpp View File

@@ -404,7 +404,7 @@ void ListBox::updateContent()
if (selected [selected.size() - 1] >= totalItems) if (selected [selected.size() - 1] >= totalItems)
{ {
selected.removeRange (totalItems, 0x7fffffff - totalItems);
selected.removeRange (totalItems, INT_MAX - totalItems);
if (selected.size() == 0) if (selected.size() == 0)
lastRowSelected = totalItems - 1; lastRowSelected = totalItems - 1;
@@ -507,7 +507,7 @@ void ListBox::deselectRow (const int row)
void ListBox::setSelectedRows (const SparseSet<int>& setOfRowsToBeSelected) void ListBox::setSelectedRows (const SparseSet<int>& setOfRowsToBeSelected)
{ {
selected = setOfRowsToBeSelected; selected = setOfRowsToBeSelected;
selected.removeRange (totalItems, 0x7fffffff - totalItems);
selected.removeRange (totalItems, INT_MAX - totalItems);
if (! isRowSelected (lastRowSelected)) if (! isRowSelected (lastRowSelected))
lastRowSelected = -1; lastRowSelected = -1;


+ 1
- 1
src/juce_appframework/gui/components/controls/juce_TableHeaderComponent.cpp View File

@@ -156,7 +156,7 @@ void TableHeaderComponent::addColumn (const String& columnName,
ci->minimumWidth = minimumWidth; ci->minimumWidth = minimumWidth;
ci->maximumWidth = maximumWidth; ci->maximumWidth = maximumWidth;
if (ci->maximumWidth < 0) if (ci->maximumWidth < 0)
ci->maximumWidth = 0x7fffffff;
ci->maximumWidth = INT_MAX;
jassert (ci->maximumWidth >= ci->minimumWidth); jassert (ci->maximumWidth >= ci->minimumWidth);
ci->propertyFlags = propertyFlags; ci->propertyFlags = propertyFlags;


+ 10
- 0
src/juce_appframework/gui/components/juce_Component.cpp View File

@@ -3188,6 +3188,16 @@ bool Component::isFocusContainer() const throw()
return flags.isFocusContainerFlag; return flags.isFocusContainerFlag;
} }


int Component::getExplicitFocusOrder() const throw()
{
return getComponentPropertyInt (T("_jexfo"), false, 0);
}
void Component::setExplicitFocusOrder (const int newFocusOrderIndex) throw()
{
setComponentProperty (T("_jexfo"), newFocusOrderIndex);
}

KeyboardFocusTraverser* Component::createFocusTraverser() KeyboardFocusTraverser* Component::createFocusTraverser()
{ {
if (flags.isFocusContainerFlag || parentComponent_ == 0) if (flags.isFocusContainerFlag || parentComponent_ == 0)


+ 58
- 11
src/juce_appframework/gui/components/juce_Component.h View File

@@ -998,10 +998,7 @@ public:
*/ */
bool getWantsKeyboardFocus() const throw(); bool getWantsKeyboardFocus() const throw();
void setFocusContainer (const bool isFocusContainer) throw();
bool isFocusContainer() const throw();
//==============================================================================
/** Chooses whether a click on this component automatically grabs the focus. /** Chooses whether a click on this component automatically grabs the focus.
By default this is set to true, but you might want a component which can By default this is set to true, but you might want a component which can
@@ -1016,6 +1013,7 @@ public:
*/ */
bool getMouseClickGrabsKeyboardFocus() const throw(); bool getMouseClickGrabsKeyboardFocus() const throw();
//==============================================================================
/** Tries to give keyboard focus to this component. /** Tries to give keyboard focus to this component.
When the user clicks on a component or its grabKeyboardFocus() When the user clicks on a component or its grabKeyboardFocus()
@@ -1049,6 +1047,13 @@ public:
*/ */
bool hasKeyboardFocus (const bool trueIfChildIsFocused) const throw(); bool hasKeyboardFocus (const bool trueIfChildIsFocused) const throw();
/** Returns the component that currently has the keyboard focus.
@returns the focused component, or null if nothing is focused.
*/
static Component* getCurrentlyFocusedComponent() throw();
//==============================================================================
/** Tries to move the keyboard focus to one of this component's siblings. /** Tries to move the keyboard focus to one of this component's siblings.
This will try to move focus to either the next or previous component. (This This will try to move focus to either the next or previous component. (This
@@ -1058,16 +1063,10 @@ public:
@param moveToNext if true, the focus will move forwards; if false, it will @param moveToNext if true, the focus will move forwards; if false, it will
move backwards move backwards
@see grabKeyboardFocus, setWantsKeyboardFocus
@see grabKeyboardFocus, setFocusContainer, setWantsKeyboardFocus
*/ */
void moveKeyboardFocusToSibling (const bool moveToNext); void moveKeyboardFocusToSibling (const bool moveToNext);
/** Returns the component that currently has the keyboard focus.
@returns the focused component, or null if nothing is focused.
*/
static Component* getCurrentlyFocusedComponent() throw();
/** Creates a KeyboardFocusTraverser object to use to determine the logic by /** Creates a KeyboardFocusTraverser object to use to determine the logic by
which focus should be passed from this component. which focus should be passed from this component.
@@ -1085,6 +1084,54 @@ public:
*/ */
virtual KeyboardFocusTraverser* createFocusTraverser(); virtual KeyboardFocusTraverser* createFocusTraverser();
/** Returns the focus order of this component, if one has been specified.
By default components don't have a focus order - in that case, this
will return 0. Lower numbers indicate that the component will be
earlier in the focus traversal order.
To change the order, call setExplicitFocusOrder().
The focus order may be used by the KeyboardFocusTraverser class as part of
its algorithm for deciding the order in which components should be traversed.
See the KeyboardFocusTraverser class for more details on this.
@see moveKeyboardFocusToSibling, createFocusTraverser, KeyboardFocusTraverser
*/
int getExplicitFocusOrder() const throw();
/** Sets the index used in determining the order in which focusable components
should be traversed.
A value of 0 or less is taken to mean that no explicit order is wanted, and
that traversal should use other factors, like the component's position.
@see getExplicitFocusOrder, moveKeyboardFocusToSibling
*/
void setExplicitFocusOrder (const int newFocusOrderIndex) throw();
/** Indicates whether this component is a parent for components that can have
their focus traversed.
This flag is used by the default implementation of the createFocusTraverser()
method, which uses the flag to find the first parent component (of the currently
focused one) which wants to be a focus container.
So using this method to set the flag to 'true' causes this component to
act as the top level within which focus is passed around.
@see isFocusContainer, createFocusTraverser, moveKeyboardFocusToSibling
*/
void setFocusContainer (const bool isFocusContainer) throw();
/** Returns true if this component has been marked as a focus container.
See setFocusContainer() for more details.
@see setFocusContainer, moveKeyboardFocusToSibling, createFocusTraverser
*/
bool isFocusContainer() const throw();
//============================================================================== //==============================================================================
/** Returns true if the component (and all its parents) are enabled. /** Returns true if the component (and all its parents) are enabled.


+ 19
- 8
src/juce_appframework/gui/components/keyboard/juce_KeyboardFocusTraverser.cpp View File

@@ -56,12 +56,21 @@ public:
static int compareElements (const Component* const first, const Component* const second) throw() static int compareElements (const Component* const first, const Component* const second) throw()
{ {
int diff = first->getY() - second->getY();
int explicitOrder1 = first->getExplicitFocusOrder();
if (explicitOrder1 < 0)
explicitOrder1 = INT_MAX / 2;
if (diff == 0)
diff = first->getX() - second->getX();
int explicitOrder2 = second->getExplicitFocusOrder();
if (explicitOrder2 < 0)
explicitOrder2 = INT_MAX / 2;
return diff;
if (explicitOrder1 != explicitOrder2)
return explicitOrder2 - explicitOrder1;
const int diff = first->getY() - second->getY();
return (diff == 0) ? first->getX() - second->getX()
: diff;
} }
}; };
@@ -94,7 +103,7 @@ static void findAllFocusableComponents (Component* const parent, Array <Componen
} }
} }
static Component* getIncrementedComponent (Component* const current, const int delta)
static Component* getIncrementedComponent (Component* const current, const int delta) throw()
{ {
Component* focusContainer = current->getParentComponent(); Component* focusContainer = current->getParentComponent();
@@ -108,9 +117,11 @@ static Component* getIncrementedComponent (Component* const current, const int d
Array <Component*> comps; Array <Component*> comps;
findAllFocusableComponents (focusContainer, comps); findAllFocusableComponents (focusContainer, comps);
const int index = comps.indexOf (current);
return comps [(index + comps.size() + delta) % comps.size()];
if (comps.size() > 0)
{
const int index = comps.indexOf (current);
return comps [(index + comps.size() + delta) % comps.size()];
}
} }
} }


+ 15
- 5
src/juce_appframework/gui/components/keyboard/juce_KeyboardFocusTraverser.h View File

@@ -39,11 +39,21 @@ class Component;
/** /**
Controls the order in which focus moves between components. Controls the order in which focus moves between components.
The default implementation of this class orders the components in a left-to-right,
top-to-bottom order. If you need traversal in a more customised way, you
can create a subclass that uses your own algorithm.
@see Component::createFocusTraverser()
The default algorithm used by this class to work out the order of traversal
is as follows:
- if two components both have an explicit focus order specified, then the
one with the lowest number comes first (see the Component::setExplicitFocusOrder()
method).
- any component with an explicit focus order greater than 0 comes before ones
that don't have an order specified.
- any unspecified components are traversed in a left-to-right, then top-to-bottom
order.
If you need traversal in a more customised way, you can create a subclass
of KeyboardFocusTraverser that uses your own algorithm, and use
Component::createFocusTraverser() to create it.
@see Component::setExplicitFocusOrder, Component::createFocusTraverser
*/ */
class JUCE_API KeyboardFocusTraverser class JUCE_API KeyboardFocusTraverser
{ {


+ 1
- 1
src/juce_appframework/gui/graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -218,7 +218,7 @@ public:
{ {
++accessCounter; ++accessCounter;
int oldestCounter = 0x7fffffff;
int oldestCounter = INT_MAX;
int oldestIndex = 0; int oldestIndex = 0;
for (int i = numGlyphs; --i >= 0;) for (int i = numGlyphs; --i >= 0;)


+ 1
- 1
src/juce_appframework/gui/graphics/fonts/juce_Typeface.cpp View File

@@ -476,7 +476,7 @@ public:
} }
int replaceIndex = 0; int replaceIndex = 0;
int bestLastUsageCount = 0x7fffffff;
int bestLastUsageCount = INT_MAX;
for (i = faces.size(); --i >= 0;) for (i = faces.size(); --i >= 0;)
{ {


+ 1
- 1
src/juce_core/text/juce_XmlElement.cpp View File

@@ -826,7 +826,7 @@ void XmlElement::insertChildElement (XmlElement* const newNode,
else else
{ {
if (indexToInsertAt < 0) if (indexToInsertAt < 0)
indexToInsertAt = 0x7fffffff;
indexToInsertAt = INT_MAX;
XmlElement* child = firstChildElement; XmlElement* child = firstChildElement;


Loading…
Cancel
Save