Browse Source

Fixed an image resizing bug. Tweaked a couple of methods in KeyMappingEditorComponent and TableListBox to return references instead of pointers. Changed Component::contains() to take a Point rather than raw coordinates. Modernised some UI classes internally. Extended some internal graphics classes to handle affine transforms.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
aef3203a28
31 changed files with 1593 additions and 1754 deletions
  1. +16
    -15
      extras/juce demo/Source/demos/TableDemo.cpp
  2. +1
    -1
      extras/the jucer/src/ui/jucer_PrefsPanel.cpp
  3. +5
    -5
      extras/the jucer/src/ui/jucer_ResourceEditorPanel.cpp
  4. +746
    -820
      juce_amalgamated.cpp
  5. +42
    -43
      juce_amalgamated.h
  6. +1
    -1
      src/core/juce_StandardHeader.h
  7. +31
    -47
      src/gui/components/controls/juce_ComboBox.cpp
  8. +1
    -1
      src/gui/components/controls/juce_Label.cpp
  9. +66
    -143
      src/gui/components/controls/juce_TableListBox.cpp
  10. +3
    -3
      src/gui/components/controls/juce_TableListBox.h
  11. +6
    -18
      src/gui/components/controls/juce_Toolbar.cpp
  12. +2
    -2
      src/gui/components/controls/juce_Toolbar.h
  13. +59
    -80
      src/gui/components/juce_Component.cpp
  14. +13
    -8
      src/gui/components/juce_Component.h
  15. +2
    -2
      src/gui/components/juce_Desktop.cpp
  16. +199
    -218
      src/gui/components/keyboard/juce_KeyMappingEditorComponent.cpp
  17. +18
    -29
      src/gui/components/keyboard/juce_KeyMappingEditorComponent.h
  18. +12
    -15
      src/gui/components/layout/juce_Viewport.cpp
  19. +1
    -0
      src/gui/components/layout/juce_Viewport.h
  20. +74
    -91
      src/gui/components/menus/juce_PopupMenu.cpp
  21. +1
    -0
      src/gui/components/menus/juce_PopupMenu.h
  22. +1
    -1
      src/gui/components/mouse/juce_MouseInputSource.cpp
  23. +81
    -114
      src/gui/components/properties/juce_PropertyPanel.cpp
  24. +1
    -0
      src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h
  25. +6
    -0
      src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp
  26. +1
    -0
      src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h
  27. +178
    -76
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
  28. +1
    -0
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h
  29. +9
    -21
      src/native/linux/juce_linux_Windowing.cpp
  30. +10
    -0
      src/native/mac/juce_mac_CoreGraphicsContext.mm
  31. +6
    -0
      src/native/windows/juce_win32_Direct2DGraphicsContext.cpp

+ 16
- 15
extras/juce demo/Source/demos/TableDemo.cpp View File

@@ -42,30 +42,31 @@ public:
loadData();
// Create our table component and add it to this component..
addAndMakeVisible (table = new TableListBox ("demo table", this));
addAndMakeVisible (&table);
table.setModel (this);
// give it a border
table->setColour (ListBox::outlineColourId, Colours::grey);
table->setOutlineThickness (1);
table.setColour (ListBox::outlineColourId, Colours::grey);
table.setOutlineThickness (1);
// Add some columns to the table header, based on the column list in our database..
forEachXmlChildElement (*columnList, columnXml)
{
table->getHeader()->addColumn (columnXml->getStringAttribute ("name"),
columnXml->getIntAttribute ("columnId"),
columnXml->getIntAttribute ("width"),
50, 400,
TableHeaderComponent::defaultFlags);
table.getHeader().addColumn (columnXml->getStringAttribute ("name"),
columnXml->getIntAttribute ("columnId"),
columnXml->getIntAttribute ("width"),
50, 400,
TableHeaderComponent::defaultFlags);
}
// we could now change some initial settings..
table->getHeader()->setSortColumnId (1, true); // sort forwards by the ID column
table->getHeader()->setColumnVisible (7, false); // hide the "length" column until the user shows it
table.getHeader().setSortColumnId (1, true); // sort forwards by the ID column
table.getHeader().setColumnVisible (7, false); // hide the "length" column until the user shows it
// un-comment this line to have a go of stretch-to-fit mode
// table->getHeader()->setStretchToFitActive (true);
// table.getHeader().setStretchToFitActive (true);
table->setMultipleSelectionEnabled (true);
table.setMultipleSelectionEnabled (true);
}
~TableDemoComponent()
@@ -119,7 +120,7 @@ public:
DemoDataSorter sorter (getAttributeNameForColumnId (newSortColumnId), isForwards);
dataList->sortChildElements (sorter);
table->updateContent();
table.updateContent();
}
}
@@ -190,14 +191,14 @@ public:
void resized()
{
// position our table with a gap around its edge
table->setBoundsInset (BorderSize (8));
table.setBoundsInset (BorderSize (8));
}
//==============================================================================
juce_UseDebuggingNewOperator
private:
ScopedPointer<TableListBox> table; // the table component itself
TableListBox table; // the table component itself
Font font;
ScopedPointer<XmlElement> demoData; // This is the XML document loaded from the embedded file "demo table data.xml"


+ 1
- 1
extras/the jucer/src/ui/jucer_PrefsPanel.cpp View File

@@ -142,7 +142,7 @@ public:
}
else if (pageName == keysPage)
{
return new KeyMappingEditorComponent (commandManager->getKeyMappings(), true);
return new KeyMappingEditorComponent (*commandManager->getKeyMappings(), true);
}
else if (pageName == aboutPage)
{


+ 5
- 5
extras/the jucer/src/ui/jucer_ResourceEditorPanel.cpp View File

@@ -95,11 +95,11 @@ ResourceEditorPanel::ResourceEditorPanel (JucerDocument& document_)
delButton->setEnabled (false);
addAndMakeVisible (listBox = new TableListBox (String::empty, this));
listBox->getHeader()->addColumn (T("name"), 1, 150, 80, 400);
listBox->getHeader()->addColumn (T("original file"), 2, 350, 80, 800);
listBox->getHeader()->addColumn (T("size"), 3, 100, 40, 150);
listBox->getHeader()->addColumn (T("reload"), 4, 100, 100, 100, TableHeaderComponent::notResizableOrSortable);
listBox->getHeader()->setStretchToFitActive (true);
listBox->getHeader().addColumn (T("name"), 1, 150, 80, 400);
listBox->getHeader().addColumn (T("original file"), 2, 350, 80, 800);
listBox->getHeader().addColumn (T("size"), 3, 100, 40, 150);
listBox->getHeader().addColumn (T("reload"), 4, 100, 100, 100, TableHeaderComponent::notResizableOrSortable);
listBox->getHeader().setStretchToFitActive (true);
listBox->setColour (ListBox::outlineColourId, Colours::darkgrey);
listBox->setOutlineThickness (1);


+ 746
- 820
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 42
- 43
juce_amalgamated.h View File

@@ -64,7 +64,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90

/** Current Juce version number.

@@ -26721,15 +26721,14 @@ public:

Never override this method! Use hitTest to create custom hit regions.

@param x the x co-ordinate to test, relative to this component's left hand edge.
@param y the y co-ordinate to test, relative to this component's top edge.
@param point the x co-ordinate to test, relative to this component's top-left.
@returns true if the point is within the component's hit-test area, but only if
that part of the component isn't clipped by its parent component. Note
that this won't take into account any overlapping sibling components
which might be in the way - for that, see reallyContains()
@see hitTest, reallyContains, getComponentAt
*/
virtual bool contains (int x, int y);
bool contains (const Point<int>& point);

/** Returns true if a given point lies in this component, taking any overlapping
siblings into account.
@@ -27914,6 +27913,9 @@ public:
/** If the component is valid, this deletes it and sets this pointer to null. */
void deleteAndZero() { delete comp; jassert (comp == 0); }

bool operator== (ComponentType* component) const throw() { return comp == component; }
bool operator!= (ComponentType* component) const throw() { return comp != component; }

juce_UseDebuggingNewOperator

private:
@@ -28056,8 +28058,6 @@ private:
const Rectangle<int>& clipRect, const Component* const compToAvoid) const;
void clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect, int deltaX, int deltaY) const;

// how much of the component is not off the edges of its parents
const Rectangle<int> getUnclippedArea() const;
void sendVisibilityChangeMessage();
const Rectangle<int> getParentOrMainMonitorBounds() const;

@@ -28067,9 +28067,14 @@ private:
// implement its methods instead of this Component method).
virtual void filesDropped (const StringArray&, int, int) {}

// components aren't allowed to have copy constructors, as this would mess up parent
// hierarchies. You might need to give your subclasses a private dummy constructor like
// this one to avoid compiler warnings.
// This is included here to cause an error if you use or overload it - it has been deprecated in
// favour of contains (const Point<int>&)
void contains (int, int);

/* Components aren't allowed to have copy constructors, as this would mess up parent hierarchies.
You might need to give your subclasses a private dummy constructor like this one to avoid
compiler warnings.
*/
Component (const Component&);
Component& operator= (const Component&);

@@ -36739,6 +36744,7 @@ private:
ScrollBar horizontalScrollBar;

void updateVisibleArea();
void deleteContentComp();

Viewport (const Viewport&);
Viewport& operator= (const Viewport&);
@@ -37105,6 +37111,7 @@ private:
friend class PopupMenuCustomComponent;
friend class MenuBarComponent;
friend class OwnedArray <Item>;
friend class OwnedArray <ItemComponent>;
friend class ScopedPointer <Window>;

OwnedArray <Item> items;
@@ -46035,12 +46042,12 @@ public:
juce_UseDebuggingNewOperator

private:
Button* missingItemsButton;
ScopedPointer<Button> missingItemsButton;
bool vertical, isEditingActive;
ToolbarItemStyle toolbarStyle;
class MissingItemsComponent;
friend class MissingItemsComponent;
Array <ToolbarItemComponent*> items;
OwnedArray <ToolbarItemComponent> items;

friend class ItemDragAndDropOverlayComponent;
static const char* const toolbarDragDescriptor;
@@ -48514,8 +48521,8 @@ public:
The model pointer passed-in can be null, in which case you can set it later
with setModel().
*/
TableListBox (const String& componentName,
TableListBoxModel* model);
TableListBox (const String& componentName = String::empty,
TableListBoxModel* model = 0);

/** Destructor. */
~TableListBox();
@@ -48528,7 +48535,7 @@ public:
TableListBoxModel* getModel() const { return model; }

/** Returns the header component being used in this table. */
TableHeaderComponent* getHeader() const { return header; }
TableHeaderComponent& getHeader() const { return *header; }

/** Changes the height of the table header component.
@see getHeaderHeight
@@ -52609,23 +52616,18 @@ private:

@see KeyPressMappingSet
*/
class JUCE_API KeyMappingEditorComponent : public Component,
public TreeViewItem,
public ChangeListener,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
class JUCE_API KeyMappingEditorComponent : public Component
{
public:

/** Creates a KeyMappingEditorComponent.

@param mappingSet this is the set of mappings to display and
edit. Make sure the mappings object is not
deleted before this component!
@param showResetToDefaultButton if true, then at the bottom of the
list, the component will include a 'reset to
defaults' button.
@param mappingSet this is the set of mappings to display and edit. Make sure the
mappings object is not deleted before this component!
@param showResetToDefaultButton if true, then at the bottom of the list, the
component will include a 'reset to defaults' button.
*/
KeyMappingEditorComponent (KeyPressMappingSet* mappingSet,
KeyMappingEditorComponent (KeyPressMappingSet& mappingSet,
bool showResetToDefaultButton);

/** Destructor. */
@@ -52639,9 +52641,8 @@ public:
void setColours (const Colour& mainBackground,
const Colour& textColour);

/** Returns the KeyPressMappingSet that this component is acting upon.
*/
KeyPressMappingSet* getMappings() const throw() { return mappings; }
/** Returns the KeyPressMappingSet that this component is acting upon. */
KeyPressMappingSet& getMappings() const throw() { return mappings; }

/** Can be overridden if some commands need to be excluded from the list.

@@ -52686,29 +52687,24 @@ public:
void parentHierarchyChanged();
/** @internal */
void resized();
/** @internal */
void changeListenerCallback (void*);
/** @internal */
bool mightContainSubItems();
/** @internal */
const String getUniqueName() const;
/** @internal */
void buttonClicked (Button* button);

juce_UseDebuggingNewOperator

private:

friend class KeyMappingTreeViewItem;
friend class KeyCategoryTreeViewItem;
friend class KeyMappingItemComponent;
friend class KeyMappingChangeButton;

KeyPressMappingSet* mappings;
KeyPressMappingSet& mappings;
TreeView tree;
TextButton resetButton;

void assignNewKey (CommandID commandID, int index);
class TopLevelItem;
class ChangeKeyButton;
class MappingItem;
class CategoryItem;
class ItemComponent;
friend class TopLevelItem;
friend class OwnedArray <ChangeKeyButton>;
friend class ScopedPointer<TopLevelItem>;
ScopedPointer<TopLevelItem> treeItem;

KeyMappingEditorComponent (const KeyMappingEditorComponent&);
KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&);
@@ -60143,6 +60139,7 @@ public:
of (0, 0).
*/
virtual void setOrigin (int x, int y) = 0;
virtual void addTransform (const AffineTransform& transform) = 0;

virtual bool clipToRectangle (const Rectangle<int>& r) = 0;
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;
@@ -60204,6 +60201,7 @@ public:

bool isVectorDevice() const;
void setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);

bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion);
@@ -60301,6 +60299,7 @@ public:
bool isVectorDevice() const;

void setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);

bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion);


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90
/** Current Juce version number.


+ 31
- 47
src/gui/components/controls/juce_ComboBox.cpp View File

@@ -40,13 +40,10 @@ ComboBox::ComboBox (const String& name)
isButtonDown (false),
separatorPending (false),
menuActive (false),
label (0)
noChoicesMessage (TRANS("(no choices)"))
{
noChoicesMessage = TRANS("(no choices)");
setRepaintsOnMouseActivity (true);
lookAndFeelChanged();
currentId.addListener (this);
}
@@ -58,7 +55,6 @@ ComboBox::~ComboBox()
PopupMenu::dismissAllActiveMenus();
label = 0;
deleteAllChildren();
}
//==============================================================================
@@ -429,30 +425,33 @@ void ComboBox::lookAndFeelChanged()
{
repaint();
Label* const newLabel = getLookAndFeel().createComboBoxTextBox (*this);
if (label != 0)
{
newLabel->setEditable (label->isEditable());
newLabel->setJustificationType (label->getJustificationType());
newLabel->setTooltip (label->getTooltip());
newLabel->setText (label->getText(), false);
}
ScopedPointer <Label> newLabel (getLookAndFeel().createComboBoxTextBox (*this));
jassert (newLabel != 0);
if (label != 0)
{
newLabel->setEditable (label->isEditable());
newLabel->setJustificationType (label->getJustificationType());
newLabel->setTooltip (label->getTooltip());
newLabel->setText (label->getText(), false);
}
label = newLabel;
label = newLabel;
}
addAndMakeVisible (newLabel);
addAndMakeVisible (label);
newLabel->addListener (this);
newLabel->addMouseListener (this, false);
label->addListener (this);
label->addMouseListener (this, false);
newLabel->setColour (Label::backgroundColourId, Colours::transparentBlack);
newLabel->setColour (Label::textColourId, findColour (ComboBox::textColourId));
label->setColour (Label::backgroundColourId, Colours::transparentBlack);
label->setColour (Label::textColourId, findColour (ComboBox::textColourId));
newLabel->setColour (TextEditor::textColourId, findColour (ComboBox::textColourId));
newLabel->setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
newLabel->setColour (TextEditor::highlightColourId, findColour (TextEditor::highlightColourId));
newLabel->setColour (TextEditor::outlineColourId, Colours::transparentBlack);
label->setColour (TextEditor::textColourId, findColour (ComboBox::textColourId));
label->setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
label->setColour (TextEditor::highlightColourId, findColour (TextEditor::highlightColourId));
label->setColour (TextEditor::outlineColourId, Colours::transparentBlack);
resized();
}
@@ -465,27 +464,23 @@ void ComboBox::colourChanged()
//==============================================================================
bool ComboBox::keyPressed (const KeyPress& key)
{
bool used = false;
if (key.isKeyCode (KeyPress::upKey)
|| key.isKeyCode (KeyPress::leftKey))
if (key.isKeyCode (KeyPress::upKey) || key.isKeyCode (KeyPress::leftKey))
{
setSelectedItemIndex (jmax (0, getSelectedItemIndex() - 1));
used = true;
return true;
}
else if (key.isKeyCode (KeyPress::downKey)
|| key.isKeyCode (KeyPress::rightKey))
else if (key.isKeyCode (KeyPress::downKey) || key.isKeyCode (KeyPress::rightKey))
{
setSelectedItemIndex (jmin (getSelectedItemIndex() + 1, getNumItems() - 1));
used = true;
return true;
}
else if (key.isKeyCode (KeyPress::returnKey))
{
showPopup();
used = true;
return true;
}
return used;
return false;
}
bool ComboBox::keyStateChanged (const bool isKeyDown)
@@ -499,17 +494,9 @@ bool ComboBox::keyStateChanged (const bool isKeyDown)
}
//==============================================================================
void ComboBox::focusGained (FocusChangeType)
{
repaint();
}
void ComboBox::focusGained (FocusChangeType) { repaint(); }
void ComboBox::focusLost (FocusChangeType) { repaint(); }
void ComboBox::focusLost (FocusChangeType)
{
repaint();
}
//==============================================================================
void ComboBox::labelTextChanged (Label*)
{
triggerAsyncUpdate();
@@ -582,11 +569,8 @@ void ComboBox::mouseDown (const MouseEvent& e)
isButtonDown = isEnabled();
if (isButtonDown
&& (e.eventComponent == this || ! label->isEditable()))
{
if (isButtonDown && (e.eventComponent == this || ! label->isEditable()))
showPopup();
}
}
void ComboBox::mouseDrag (const MouseEvent& e)


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

@@ -332,7 +332,7 @@ void Label::mouseUp (const MouseEvent& e)
{
if (editSingleClick
&& e.mouseWasClicked()
&& contains (e.x, e.y)
&& contains (e.getPosition())
&& ! e.mods.isPopupMenu())
{
showEditor();


+ 66
- 143
src/gui/components/controls/juce_TableListBox.cpp View File

@@ -36,51 +36,37 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
static const char* const tableColumnPropertyTag = "_tableColumnID";
class TableListRowComp : public Component,
public TooltipClient
{
public:
TableListRowComp (TableListBox& owner_)
: owner (owner_),
row (-1),
isSelected (false)
: owner (owner_), row (-1), isSelected (false)
{
}
~TableListRowComp()
{
deleteAllChildren();
}
void paint (Graphics& g)
{
TableListBoxModel* const model = owner.getModel();
if (model != 0)
{
const TableHeaderComponent* const header = owner.getHeader();
model->paintRowBackground (g, row, getWidth(), getHeight(), isSelected);
const int numColumns = header->getNumColumns (true);
const TableHeaderComponent& header = owner.getHeader();
const int numColumns = header.getNumColumns (true);
for (int i = 0; i < numColumns; ++i)
{
if (! columnsWithComponents [i])
if (columnComponents[i] == 0)
{
const int columnId = header->getColumnIdOfIndex (i, true);
Rectangle<int> columnRect (header->getColumnPosition (i));
columnRect.setSize (columnRect.getWidth(), getHeight());
const int columnId = header.getColumnIdOfIndex (i, true);
const Rectangle<int> columnRect (header.getColumnPosition(i).withHeight (getHeight()));
g.saveState();
g.reduceClipRegion (columnRect);
g.setOrigin (columnRect.getX(), 0);
model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected);
g.restoreState();
}
}
@@ -89,79 +75,66 @@ public:
void update (const int newRow, const bool isNowSelected)
{
jassert (newRow >= 0);
if (newRow != row || isNowSelected != isSelected)
{
row = newRow;
isSelected = isNowSelected;
repaint();
deleteAllChildren();
}
if (row < owner.getNumRows())
{
jassert (row >= 0);
const Identifier tagPropertyName ("_tableLastUseNum");
const int newTag = Random::getSystemRandom().nextInt();
const TableHeaderComponent* const header = owner.getHeader();
const int numColumns = header->getNumColumns (true);
TableListBoxModel* const model = owner.getModel();
columnsWithComponents.clear();
if (model != 0 && row < owner.getNumRows())
{
const Identifier columnProperty ("_tableColumnId");
const int numColumns = owner.getHeader().getNumColumns (true);
if (owner.getModel() != 0)
for (int i = 0; i < numColumns; ++i)
{
for (int i = 0; i < numColumns; ++i)
{
const int columnId = header->getColumnIdOfIndex (i, true);
const int columnId = owner.getHeader().getColumnIdOfIndex (i, true);
Component* comp = columnComponents[i];
Component* const newComp
= owner.getModel()->refreshComponentForCell (row, columnId, isSelected,
findChildComponentForColumn (columnId));
if (comp != 0 && columnId != (int) comp->getProperties() [columnProperty])
{
columnComponents.set (i, 0);
comp = 0;
}
if (newComp != 0)
{
addAndMakeVisible (newComp);
newComp->getProperties().set (tagPropertyName, newTag);
newComp->getProperties().set (tableColumnPropertyTag, columnId);
comp = model->refreshComponentForCell (row, columnId, isSelected, comp);
columnComponents.set (i, comp);
const Rectangle<int> columnRect (header->getColumnPosition (i));
newComp->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight());
if (comp != 0)
{
comp->getProperties().set (columnProperty, columnId);
columnsWithComponents.setBit (i);
}
addAndMakeVisible (comp);
resizeCustomComp (i);
}
}
for (int i = getNumChildComponents(); --i >= 0;)
{
Component* const c = getChildComponent (i);
if ((int) c->getProperties() [tagPropertyName] != newTag)
delete c;
}
columnComponents.removeRange (numColumns, columnComponents.size());
}
else
{
columnsWithComponents.clear();
deleteAllChildren();
columnComponents.clear();
}
}
void resized()
{
for (int i = getNumChildComponents(); --i >= 0;)
{
Component* const c = getChildComponent (i);
for (int i = columnComponents.size(); --i >= 0;)
resizeCustomComp (i);
}
const int columnId = c->getProperties() [tableColumnPropertyTag];
void resizeCustomComp (const int index)
{
Component* const c = columnComponents.getUnchecked (index);
if (columnId != 0)
{
const Rectangle<int> columnRect (owner.getHeader()->getColumnPosition (owner.getHeader()->getIndexOfColumnId (columnId, true)));
c->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight());
}
}
if (c != 0)
c->setBounds (owner.getHeader().getColumnPosition (index)
.withY (0).withHeight (getHeight()));
}
void mouseDown (const MouseEvent& e)
@@ -175,7 +148,7 @@ public:
{
owner.selectRowsBasedOnModifierKeys (row, e.mods);
const int columnId = owner.getHeader()->getColumnIdAtX (e.x);
const int columnId = owner.getHeader().getColumnIdAtX (e.x);
if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellClicked (row, columnId, e);
@@ -212,7 +185,7 @@ public:
{
owner.selectRowsBasedOnModifierKeys (row, e.mods);
const int columnId = owner.getHeader()->getColumnIdAtX (e.x);
const int columnId = owner.getHeader().getColumnIdAtX (e.x);
if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellClicked (row, columnId, e);
@@ -221,7 +194,7 @@ public:
void mouseDoubleClick (const MouseEvent& e)
{
const int columnId = owner.getHeader()->getColumnIdAtX (e.x);
const int columnId = owner.getHeader().getColumnIdAtX (e.x);
if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellDoubleClicked (row, columnId, e);
@@ -229,7 +202,7 @@ public:
const String getTooltip()
{
const int columnId = owner.getHeader()->getColumnIdAtX (getMouseXYRelative().getX());
const int columnId = owner.getHeader().getColumnIdAtX (getMouseXYRelative().getX());
if (columnId != 0 && owner.getModel() != 0)
return owner.getModel()->getCellTooltip (row, columnId);
@@ -239,24 +212,16 @@ public:
Component* findChildComponentForColumn (const int columnId) const
{
for (int i = getNumChildComponents(); --i >= 0;)
{
Component* const c = getChildComponent (i);
if ((int) c->getProperties() [tableColumnPropertyTag] == columnId)
return c;
}
return 0;
return columnComponents [owner.getHeader().getIndexOfColumnId (columnId, true)];
}
juce_UseDebuggingNewOperator
private:
TableListBox& owner;
OwnedArray<Component> columnComponents;
int row;
bool isSelected, isDragging, selectRowOnMouseUp;
BigInteger columnsWithComponents;
TableListRowComp (const TableListRowComp&);
TableListRowComp& operator= (const TableListRowComp&);
@@ -277,7 +242,7 @@ public:
if (owner.isAutoSizeMenuOptionShown())
{
menu.addItem (autoSizeColumnId, TRANS("Auto-size this column"), columnIdClicked != 0);
menu.addItem (autoSizeAllId, TRANS("Auto-size all columns"), owner.getHeader()->getNumColumns (true) > 0);
menu.addItem (autoSizeAllId, TRANS("Auto-size all columns"), owner.getHeader().getNumColumns (true) > 0);
menu.addSeparator();
}
@@ -286,17 +251,11 @@ public:
void reactToMenuItem (int menuReturnId, int columnIdClicked)
{
if (menuReturnId == autoSizeColumnId)
switch (menuReturnId)
{
owner.autoSizeColumn (columnIdClicked);
}
else if (menuReturnId == autoSizeAllId)
{
owner.autoSizeAllColumns();
}
else
{
TableHeaderComponent::reactToMenuItem (menuReturnId, columnIdClicked);
case autoSizeColumnId: owner.autoSizeColumn (columnIdClicked); break;
case autoSizeAllId: owner.autoSizeAllColumns(); break;
default: TableHeaderComponent::reactToMenuItem (menuReturnId, columnIdClicked); break;
}
}
@@ -375,8 +334,7 @@ bool TableListBox::isAutoSizeMenuOptionShown() const
return autoSizeOptionsShown;
}
const Rectangle<int> TableListBox::getCellPosition (const int columnId,
const int rowNumber,
const Rectangle<int> TableListBox::getCellPosition (const int columnId, const int rowNumber,
const bool relativeToComponentTopLeft) const
{
Rectangle<int> headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true)));
@@ -384,10 +342,9 @@ const Rectangle<int> TableListBox::getCellPosition (const int columnId,
if (relativeToComponentTopLeft)
headerCell.translate (header->getX(), 0);
const Rectangle<int> row (getRowPosition (rowNumber, relativeToComponentTopLeft));
return Rectangle<int> (headerCell.getX(), row.getY(),
headerCell.getWidth(), row.getHeight());
return getRowPosition (rowNumber, relativeToComponentTopLeft)
.withX (headerCell.getX())
.withWidth (headerCell.getWidth());
}
Component* TableListBox::getCellComponent (int columnId, int rowNumber) const
@@ -514,52 +471,18 @@ void TableListBox::updateColumnComponents() const
}
//==============================================================================
void TableListBoxModel::cellClicked (int, int, const MouseEvent&)
{
}
void TableListBoxModel::cellDoubleClicked (int, int, const MouseEvent&)
{
}
void TableListBoxModel::backgroundClicked()
{
}
void TableListBoxModel::sortOrderChanged (int, const bool)
{
}
int TableListBoxModel::getColumnAutoSizeWidth (int)
{
return 0;
}
void TableListBoxModel::selectedRowsChanged (int)
{
}
void TableListBoxModel::deleteKeyPressed (int)
{
}
void TableListBoxModel::returnKeyPressed (int)
{
}
void TableListBoxModel::listWasScrolled()
{
}
const String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/)
{
return String::empty;
}
const String TableListBoxModel::getDragSourceDescription (const SparseSet<int>&)
{
return String::empty;
}
void TableListBoxModel::cellClicked (int, int, const MouseEvent&) {}
void TableListBoxModel::cellDoubleClicked (int, int, const MouseEvent&) {}
void TableListBoxModel::backgroundClicked() {}
void TableListBoxModel::sortOrderChanged (int, const bool) {}
int TableListBoxModel::getColumnAutoSizeWidth (int) { return 0; }
void TableListBoxModel::selectedRowsChanged (int) {}
void TableListBoxModel::deleteKeyPressed (int) {}
void TableListBoxModel::returnKeyPressed (int) {}
void TableListBoxModel::listWasScrolled() {}
const String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { return String::empty; }
const String TableListBoxModel::getDragSourceDescription (const SparseSet<int>&) { return String::empty; }
Component* TableListBoxModel::refreshComponentForCell (int, int, bool, Component* existingComponentToUpdate)
{


+ 3
- 3
src/gui/components/controls/juce_TableListBox.h View File

@@ -208,8 +208,8 @@ public:
The model pointer passed-in can be null, in which case you can set it later
with setModel().
*/
TableListBox (const String& componentName,
TableListBoxModel* model);
TableListBox (const String& componentName = String::empty,
TableListBoxModel* model = 0);
/** Destructor. */
~TableListBox();
@@ -224,7 +224,7 @@ public:
//==============================================================================
/** Returns the header component being used in this table. */
TableHeaderComponent* getHeader() const { return header; }
TableHeaderComponent& getHeader() const { return *header; }
/** Changes the height of the table header component.
@see getHeaderHeight


+ 6
- 18
src/gui/components/controls/juce_Toolbar.cpp View File

@@ -281,7 +281,7 @@ Toolbar::Toolbar()
Toolbar::~Toolbar()
{
deleteAllChildren();
items.clear();
}
void Toolbar::setVertical (const bool shouldBeVertical)
@@ -295,13 +295,7 @@ void Toolbar::setVertical (const bool shouldBeVertical)
void Toolbar::clear()
{
for (int i = items.size(); --i >= 0;)
{
ToolbarItemComponent* const tc = items.getUnchecked(i);
items.remove (i);
delete tc;
}
items.clear();
resized();
}
@@ -365,14 +359,8 @@ void Toolbar::addDefaultItems (ToolbarItemFactory& factoryToUse)
void Toolbar::removeToolbarItem (const int itemIndex)
{
ToolbarItemComponent* const tc = getItemComponent (itemIndex);
if (tc != 0)
{
items.removeValue (tc);
delete tc;
resized();
}
items.remove (itemIndex);
resized();
}
int Toolbar::getNumItems() const throw()
@@ -672,7 +660,7 @@ void Toolbar::itemDragMove (const String&, Component* sourceComponent, int x, in
if (newIndex != currentIndex)
{
items.removeValue (tc);
items.removeObject (tc, false);
removeChildComponent (tc);
addChildComponent (tc, newIndex);
items.insert (newIndex, tc);
@@ -695,7 +683,7 @@ void Toolbar::itemDragExit (const String&, Component* sourceComponent)
{
if (isParentOf (tc))
{
items.removeValue (tc);
items.removeObject (tc, false);
removeChildComponent (tc);
updateAllItemPositions (true);
}


+ 2
- 2
src/gui/components/controls/juce_Toolbar.h View File

@@ -294,12 +294,12 @@ public:
juce_UseDebuggingNewOperator
private:
Button* missingItemsButton;
ScopedPointer<Button> missingItemsButton;
bool vertical, isEditingActive;
ToolbarItemStyle toolbarStyle;
class MissingItemsComponent;
friend class MissingItemsComponent;
Array <ToolbarItemComponent*> items;
OwnedArray <ToolbarItemComponent> items;
friend class ItemDragAndDropOverlayComponent;
static const char* const toolbarDragDescriptor;


+ 59
- 80
src/gui/components/juce_Component.cpp View File

@@ -786,36 +786,43 @@ const Rectangle<int> Component::getScreenBounds() const
namespace CoordinateHelpers
{
const Point<int> convertFromParentSpace (const Component* comp, const Point<int>& pointInParentSpace)
inline bool hitTest (Component& comp, const Point<int>& localPoint)
{
return pointInParentSpace - comp->getPosition();
return ((unsigned int) localPoint.getX()) < (unsigned int) comp.getWidth()
&& ((unsigned int) localPoint.getY()) < (unsigned int) comp.getHeight()
&& comp.hitTest (localPoint.getX(), localPoint.getY());
}
const Rectangle<int> convertFromParentSpace (const Component* comp, const Rectangle<int>& areaInParentSpace)
const Point<int> convertFromParentSpace (const Component& comp, const Point<int>& pointInParentSpace)
{
return areaInParentSpace - comp->getPosition();
return pointInParentSpace - comp.getPosition();
}
const Point<int> convertToParentSpace (const Component* comp, const Point<int>& pointInLocalSpace)
const Rectangle<int> convertFromParentSpace (const Component& comp, const Rectangle<int>& areaInParentSpace)
{
return pointInLocalSpace + comp->getPosition();
return areaInParentSpace - comp.getPosition();
}
const Rectangle<int> convertToParentSpace (const Component* comp, const Rectangle<int>& areaInLocalSpace)
const Point<int> convertToParentSpace (const Component& comp, const Point<int>& pointInLocalSpace)
{
return areaInLocalSpace + comp->getPosition();
return pointInLocalSpace + comp.getPosition();
}
const Rectangle<int> convertToParentSpace (const Component& comp, const Rectangle<int>& areaInLocalSpace)
{
return areaInLocalSpace + comp.getPosition();
}
template <typename Type>
const Type convertFromDistantParentSpace (const Component* parent, const Component* target, Type coordInParent)
const Type convertFromDistantParentSpace (const Component* parent, const Component& target, Type coordInParent)
{
const Component* const directParent = target->getParentComponent();
const Component* const directParent = target.getParentComponent();
jassert (directParent != 0);
if (directParent == parent)
return convertFromParentSpace (target, coordInParent);
return convertFromParentSpace (target, convertFromDistantParentSpace (parent, directParent, coordInParent));
return convertFromParentSpace (target, convertFromDistantParentSpace (parent, *directParent, coordInParent));
}
template <typename Type>
@@ -827,7 +834,7 @@ namespace CoordinateHelpers
return p;
if (source->isParentOf (target))
return convertFromDistantParentSpace (source, target, p);
return convertFromDistantParentSpace (source, *target, p);
if (source->isOnDesktop())
{
@@ -836,7 +843,7 @@ namespace CoordinateHelpers
}
else
{
p = convertToParentSpace (source, p);
p = convertToParentSpace (*source, p);
source = source->getParentComponent();
}
}
@@ -850,12 +857,24 @@ namespace CoordinateHelpers
if (topLevelComp->isOnDesktop())
p = topLevelComp->getPeer()->globalToLocal (p);
else
p = convertFromParentSpace (topLevelComp, p);
p = convertFromParentSpace (*topLevelComp, p);
if (topLevelComp == target)
return p;
return convertFromDistantParentSpace (topLevelComp, target, p);
return convertFromDistantParentSpace (topLevelComp, *target, p);
}
const Rectangle<int> getUnclippedArea (const Component& comp)
{
Rectangle<int> r (comp.getLocalBounds());
Component* const p = comp.getParentComponent();
if (p != 0)
r = r.getIntersection (convertFromParentSpace (comp, getUnclippedArea (*p)));
return r;
}
}
@@ -1100,15 +1119,11 @@ bool Component::hitTest (int x, int y)
{
for (int i = getNumChildComponents(); --i >= 0;)
{
Component* const c = getChildComponent (i);
Component& child = *getChildComponent (i);
if (c->isVisible()
&& c->bounds_.contains (x, y)
&& c->hitTest (x - c->getX(),
y - c->getY()))
{
if (child.isVisible()
&& CoordinateHelpers::hitTest (child, CoordinateHelpers::convertFromParentSpace (child, Point<int> (x, y))))
return true;
}
}
}
@@ -1129,70 +1144,50 @@ void Component::getInterceptsMouseClicks (bool& allowsClicksOnThisComponent,
allowsClicksOnChildComponents = flags.allowChildMouseClicksFlag;
}
bool Component::contains (const int x, const int y)
bool Component::contains (const Point<int>& point)
{
if (((unsigned int) x) < (unsigned int) getWidth()
&& ((unsigned int) y) < (unsigned int) getHeight()
&& hitTest (x, y))
if (CoordinateHelpers::hitTest (*this, point))
{
if (parentComponent_ != 0)
{
return parentComponent_->contains (x + getX(),
y + getY());
return parentComponent_->contains (CoordinateHelpers::convertToParentSpace (*this, point));
}
else if (flags.hasHeavyweightPeerFlag)
{
const ComponentPeer* const peer = getPeer();
if (peer != 0)
return peer->contains (Point<int> (x, y), true);
return peer->contains (point, true);
}
}
return false;
}
bool Component::reallyContains (int x, int y, const bool returnTrueIfWithinAChild)
bool Component::reallyContains (const int x, const int y, const bool returnTrueIfWithinAChild)
{
if (! contains (x, y))
return false;
const Point<int> p (x, y);
Component* p = this;
while (p->parentComponent_ != 0)
{
x += p->getX();
y += p->getY();
p = p->parentComponent_;
}
if (! contains (p))
return false;
const Component* const c = p->getComponentAt (x, y);
Component* const top = getTopLevelComponent();
const Component* const compAtPosition = top->getComponentAt (top->getLocalPoint (this, p));
return (c == this) || (returnTrueIfWithinAChild && isParentOf (c));
return (compAtPosition == this) || (returnTrueIfWithinAChild && isParentOf (compAtPosition));
}
Component* Component::getComponentAt (const Point<int>& position)
{
return getComponentAt (position.getX(), position.getY());
}
Component* Component::getComponentAt (const int x, const int y)
{
if (flags.visibleFlag
&& ((unsigned int) x) < (unsigned int) getWidth()
&& ((unsigned int) y) < (unsigned int) getHeight()
&& hitTest (x, y))
if (flags.visibleFlag && CoordinateHelpers::hitTest (*this, position))
{
for (int i = childComponentList_.size(); --i >= 0;)
{
Component* const child = childComponentList_.getUnchecked(i);
Component* child = childComponentList_.getUnchecked(i);
child = child->getComponentAt (CoordinateHelpers::convertFromParentSpace (*child, position));
Component* const c = child->getComponentAt (x - child->getX(),
y - child->getY());
if (c != 0)
return c;
if (child != 0)
return child;
}
return this;
@@ -1201,6 +1196,11 @@ Component* Component::getComponentAt (const int x, const int y)
return 0;
}
Component* Component::getComponentAt (const int x, const int y)
{
return getComponentAt (Point<int> (x, y));
}
//==============================================================================
void Component::addChildComponent (Component* const child, int zOrder)
{
@@ -1925,27 +1925,6 @@ const Rectangle<int> Component::getParentOrMainMonitorBounds() const
: Desktop::getInstance().getMainMonitorArea();
}
const Rectangle<int> Component::getUnclippedArea() const
{
int x = 0, y = 0, w = getWidth(), h = getHeight();
Component* p = parentComponent_;
int px = getX();
int py = getY();
while (p != 0)
{
if (! Rectangle<int>::intersectRectangles (x, y, w, h, -px, -py, p->getWidth(), p->getHeight()))
return Rectangle<int>();
px += p->getX();
py += p->getY();
p = p->parentComponent_;
}
return Rectangle<int> (x, y, w, h);
}
void Component::clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect,
const int deltaX, const int deltaY) const
{
@@ -1977,7 +1956,7 @@ void Component::clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect
void Component::getVisibleArea (RectangleList& result, const bool includeSiblings) const
{
result.clear();
const Rectangle<int> unclipped (getUnclippedArea());
const Rectangle<int> unclipped (CoordinateHelpers::getUnclippedArea (*this));
if (! unclipped.isEmpty())
{


+ 13
- 8
src/gui/components/juce_Component.h View File

@@ -728,15 +728,14 @@ public:
Never override this method! Use hitTest to create custom hit regions.
@param x the x co-ordinate to test, relative to this component's left hand edge.
@param y the y co-ordinate to test, relative to this component's top edge.
@param point the x co-ordinate to test, relative to this component's top-left.
@returns true if the point is within the component's hit-test area, but only if
that part of the component isn't clipped by its parent component. Note
that this won't take into account any overlapping sibling components
which might be in the way - for that, see reallyContains()
@see hitTest, reallyContains, getComponentAt
*/
virtual bool contains (int x, int y);
bool contains (const Point<int>& point);
/** Returns true if a given point lies in this component, taking any overlapping
siblings into account.
@@ -1949,6 +1948,9 @@ public:
/** If the component is valid, this deletes it and sets this pointer to null. */
void deleteAndZero() { delete comp; jassert (comp == 0); }
bool operator== (ComponentType* component) const throw() { return comp == component; }
bool operator!= (ComponentType* component) const throw() { return comp != component; }
//==============================================================================
juce_UseDebuggingNewOperator
@@ -2097,8 +2099,6 @@ private:
const Rectangle<int>& clipRect, const Component* const compToAvoid) const;
void clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect, int deltaX, int deltaY) const;
// how much of the component is not off the edges of its parents
const Rectangle<int> getUnclippedArea() const;
void sendVisibilityChangeMessage();
const Rectangle<int> getParentOrMainMonitorBounds() const;
@@ -2109,9 +2109,14 @@ private:
// implement its methods instead of this Component method).
virtual void filesDropped (const StringArray&, int, int) {}
// components aren't allowed to have copy constructors, as this would mess up parent
// hierarchies. You might need to give your subclasses a private dummy constructor like
// this one to avoid compiler warnings.
// This is included here to cause an error if you use or overload it - it has been deprecated in
// favour of contains (const Point<int>&)
void contains (int, int);
/* Components aren't allowed to have copy constructors, as this would mess up parent hierarchies.
You might need to give your subclasses a private dummy constructor like this one to avoid
compiler warnings.
*/
Component (const Component&);
Component& operator= (const Component&);


+ 2
- 2
src/gui/components/juce_Desktop.cpp View File

@@ -162,8 +162,8 @@ Component* Desktop::findComponentAt (const Point<int>& screenPosition) const
{
const Point<int> relative (c->getLocalPoint (0, screenPosition));
if (c->contains (relative.getX(), relative.getY()))
return c->getComponentAt (relative.getX(), relative.getY());
if (c->contains (relative))
return c->getComponentAt (relative);
}
}


+ 199
- 218
src/gui/components/keyboard/juce_KeyMappingEditorComponent.cpp View File

@@ -40,13 +40,13 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
class KeyMappingChangeButton : public Button
class KeyMappingEditorComponent::ChangeKeyButton : public Button
{
public:
KeyMappingChangeButton (KeyMappingEditorComponent& owner_,
const CommandID commandID_,
const String& keyName,
const int keyNum_)
ChangeKeyButton (KeyMappingEditorComponent& owner_,
const CommandID commandID_,
const String& keyName,
const int keyNum_)
: Button (keyName),
owner (owner_),
commandID (commandID_),
@@ -75,21 +75,16 @@ public:
m.addSeparator();
m.addItem (2, TRANS("remove this key-mapping"));
const int res = m.show();
if (res == 1)
{
owner.assignNewKey (commandID, keyNum);
}
else if (res == 2)
switch (m.show())
{
owner.getMappings()->removeKeyPress (commandID, keyNum);
case 1: assignNewKey(); break;
case 2: owner.getMappings().removeKeyPress (commandID, keyNum); break;
default: break;
}
}
else
{
// + button pressed..
owner.assignNewKey (commandID, -1);
assignNewKey(); // + button pressed..
}
}
@@ -106,6 +101,88 @@ public:
}
}
//==============================================================================
class KeyEntryWindow : public AlertWindow
{
public:
KeyEntryWindow (KeyMappingEditorComponent& owner_)
: AlertWindow (TRANS("New key-mapping"),
TRANS("Please press a key combination now..."),
AlertWindow::NoIcon),
owner (owner_)
{
addButton (TRANS("Ok"), 1);
addButton (TRANS("Cancel"), 0);
// (avoid return + escape keys getting processed by the buttons..)
for (int i = getNumChildComponents(); --i >= 0;)
getChildComponent (i)->setWantsKeyboardFocus (false);
setWantsKeyboardFocus (true);
grabKeyboardFocus();
}
bool keyPressed (const KeyPress& key)
{
lastPress = key;
String message (TRANS("Key: ") + owner.getDescriptionForKeyPress (key));
const CommandID previousCommand = owner.getMappings().findCommandForKeyPress (key);
if (previousCommand != 0)
message << "\n\n" << TRANS("(Currently assigned to \"")
<< owner.getMappings().getCommandManager()->getNameOfCommand (previousCommand) << "\")";
setMessage (message);
return true;
}
bool keyStateChanged (bool)
{
return true;
}
KeyPress lastPress;
private:
KeyMappingEditorComponent& owner;
KeyEntryWindow (const KeyEntryWindow&);
KeyEntryWindow& operator= (const KeyEntryWindow&);
};
void assignNewKey()
{
KeyEntryWindow entryWindow (owner);
if (entryWindow.runModalLoop() != 0)
{
entryWindow.setVisible (false);
if (entryWindow.lastPress.isValid())
{
const CommandID previousCommand = owner.getMappings().findCommandForKeyPress (entryWindow.lastPress);
if (previousCommand == 0
|| AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
TRANS("Change key-mapping"),
TRANS("This key is already assigned to the command \"")
+ owner.getMappings().getCommandManager()->getNameOfCommand (previousCommand)
+ TRANS("\"\n\nDo you want to re-assign it to this new command instead?"),
TRANS("Re-assign"),
TRANS("Cancel")))
{
owner.getMappings().removeKeyPress (entryWindow.lastPress);
if (keyNum >= 0)
owner.getMappings().removeKeyPress (commandID, keyNum);
owner.getMappings().addKeyPress (commandID, entryWindow.lastPress, keyNum);
}
}
}
}
juce_UseDebuggingNewOperator
private:
@@ -113,43 +190,37 @@ private:
const CommandID commandID;
const int keyNum;
KeyMappingChangeButton (const KeyMappingChangeButton&);
KeyMappingChangeButton& operator= (const KeyMappingChangeButton&);
ChangeKeyButton (const ChangeKeyButton&);
ChangeKeyButton& operator= (const ChangeKeyButton&);
};
//==============================================================================
class KeyMappingItemComponent : public Component
class KeyMappingEditorComponent::ItemComponent : public Component
{
public:
KeyMappingItemComponent (KeyMappingEditorComponent& owner_, const CommandID commandID_)
ItemComponent (KeyMappingEditorComponent& owner_, const CommandID commandID_)
: owner (owner_), commandID (commandID_)
{
setInterceptsMouseClicks (false, true);
const bool isReadOnly = owner.isCommandReadOnly (commandID);
const Array <KeyPress> keyPresses (owner.getMappings()->getKeyPressesAssignedToCommand (commandID));
const Array <KeyPress> keyPresses (owner.getMappings().getKeyPressesAssignedToCommand (commandID));
for (int i = 0; i < jmin ((int) maxNumAssignments, keyPresses.size()); ++i)
{
KeyMappingChangeButton* const kb
= new KeyMappingChangeButton (owner, commandID,
owner.getDescriptionForKeyPress (keyPresses.getReference (i)), i);
kb->setEnabled (! isReadOnly);
addAndMakeVisible (kb);
}
addKeyPressButton (owner.getDescriptionForKeyPress (keyPresses.getReference (i)), i, isReadOnly);
KeyMappingChangeButton* const kb
= new KeyMappingChangeButton (owner, commandID, String::empty, -1);
addChildComponent (kb);
kb->setVisible (keyPresses.size() < (int) maxNumAssignments && ! isReadOnly);
addKeyPressButton (String::empty, -1, isReadOnly);
}
~KeyMappingItemComponent()
void addKeyPressButton (const String& desc, const int index, const bool isReadOnly)
{
deleteAllChildren();
ChangeKeyButton* const b = new ChangeKeyButton (owner, commandID, desc, index);
keyChangeButtons.add (b);
b->setEnabled (! isReadOnly);
b->setVisible (keyChangeButtons.size() <= (int) maxNumAssignments);
addChildComponent (b);
}
void paint (Graphics& g)
@@ -157,7 +228,7 @@ public:
g.setFont (getHeight() * 0.7f);
g.setColour (findColour (KeyMappingEditorComponent::textColourId));
g.drawFittedText (owner.getMappings()->getCommandManager()->getNameOfCommand (commandID),
g.drawFittedText (owner.getMappings().getCommandManager()->getNameOfCommand (commandID),
4, 0, jmax (40, getChildComponent (0)->getX() - 5), getHeight(),
Justification::centredLeft, true);
}
@@ -166,33 +237,34 @@ public:
{
int x = getWidth() - 4;
for (int i = getNumChildComponents(); --i >= 0;)
for (int i = keyChangeButtons.size(); --i >= 0;)
{
KeyMappingChangeButton* const kb = dynamic_cast <KeyMappingChangeButton*> (getChildComponent (i));
ChangeKeyButton* const b = keyChangeButtons.getUnchecked(i);
kb->fitToContent (getHeight() - 2);
kb->setTopRightPosition (x, 1);
x -= kb->getWidth() + 5;
b->fitToContent (getHeight() - 2);
b->setTopRightPosition (x, 1);
x = b->getX() - 5;
}
}
enum { maxNumAssignments = 3 };
juce_UseDebuggingNewOperator
private:
KeyMappingEditorComponent& owner;
OwnedArray<ChangeKeyButton> keyChangeButtons;
const CommandID commandID;
KeyMappingItemComponent (const KeyMappingItemComponent&);
KeyMappingItemComponent& operator= (const KeyMappingItemComponent&);
enum { maxNumAssignments = 3 };
ItemComponent (const ItemComponent&);
ItemComponent& operator= (const ItemComponent&);
};
//==============================================================================
class KeyMappingTreeViewItem : public TreeViewItem
class KeyMappingEditorComponent::MappingItem : public TreeViewItem
{
public:
KeyMappingTreeViewItem (KeyMappingEditorComponent& owner_, const CommandID commandID_)
MappingItem (KeyMappingEditorComponent& owner_, const CommandID commandID_)
: owner (owner_), commandID (commandID_)
{
}
@@ -203,7 +275,7 @@ public:
Component* createItemComponent()
{
return new KeyMappingItemComponent (owner, commandID);
return new ItemComponent (owner, commandID);
}
juce_UseDebuggingNewOperator
@@ -212,16 +284,16 @@ private:
KeyMappingEditorComponent& owner;
const CommandID commandID;
KeyMappingTreeViewItem (const KeyMappingTreeViewItem&);
KeyMappingTreeViewItem& operator= (const KeyMappingTreeViewItem&);
MappingItem (const MappingItem&);
MappingItem& operator= (const MappingItem&);
};
//==============================================================================
class KeyCategoryTreeViewItem : public TreeViewItem
class KeyMappingEditorComponent::CategoryItem : public TreeViewItem
{
public:
KeyCategoryTreeViewItem (KeyMappingEditorComponent& owner_, const String& name)
CategoryItem (KeyMappingEditorComponent& owner_, const String& name)
: owner (owner_), categoryName (name)
{
}
@@ -246,12 +318,12 @@ public:
{
if (getNumSubItems() == 0)
{
Array <CommandID> commands (owner.getMappings()->getCommandManager()->getCommandsInCategory (categoryName));
Array <CommandID> commands (owner.getMappings().getCommandManager()->getCommandsInCategory (categoryName));
for (int i = 0; i < commands.size(); ++i)
{
if (owner.shouldCommandBeIncluded (commands[i]))
addSubItem (new KeyMappingTreeViewItem (owner, commands[i]));
addSubItem (new MappingItem (owner, commands[i]));
}
}
}
@@ -267,52 +339,99 @@ private:
KeyMappingEditorComponent& owner;
String categoryName;
KeyCategoryTreeViewItem (const KeyCategoryTreeViewItem&);
KeyCategoryTreeViewItem& operator= (const KeyCategoryTreeViewItem&);
CategoryItem (const CategoryItem&);
CategoryItem& operator= (const CategoryItem&);
};
//==============================================================================
class KeyMappingEditorComponent::TopLevelItem : public TreeViewItem,
public ChangeListener,
public ButtonListener
{
public:
TopLevelItem (KeyMappingEditorComponent& owner_)
: owner (owner_)
{
setLinesDrawnForSubItems (false);
owner.getMappings().addChangeListener (this);
}
~TopLevelItem()
{
owner.getMappings().removeChangeListener (this);
}
bool mightContainSubItems() { return true; }
const String getUniqueName() const { return "keys"; }
void changeListenerCallback (void*)
{
const ScopedPointer <XmlElement> oldOpenness (owner.tree.getOpennessState (true));
clearSubItems();
const StringArray categories (owner.getMappings().getCommandManager()->getCommandCategories());
for (int i = 0; i < categories.size(); ++i)
{
const Array <CommandID> commands (owner.getMappings().getCommandManager()->getCommandsInCategory (categories[i]));
int count = 0;
for (int j = 0; j < commands.size(); ++j)
if (owner.shouldCommandBeIncluded (commands[j]))
++count;
if (count > 0)
addSubItem (new CategoryItem (owner, categories[i]));
}
if (oldOpenness != 0)
owner.tree.restoreOpennessState (*oldOpenness);
}
void buttonClicked (Button*)
{
if (AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon,
TRANS("Reset to defaults"),
TRANS("Are you sure you want to reset all the key-mappings to their default state?"),
TRANS("Reset")))
{
owner.getMappings().resetToDefaultMappings();
}
}
private:
KeyMappingEditorComponent& owner;
};
//==============================================================================
KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet* const mappingManager,
KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet& mappingManager,
const bool showResetToDefaultButton)
: mappings (mappingManager),
resetButton (TRANS ("reset to defaults"))
{
jassert (mappingManager != 0); // can't be null!
mappingManager->addChangeListener (this);
setLinesDrawnForSubItems (false);
treeItem = new TopLevelItem (*this);
if (showResetToDefaultButton)
{
addAndMakeVisible (&resetButton);
resetButton.addButtonListener (this);
resetButton.addButtonListener (treeItem);
}
addAndMakeVisible (&tree);
tree.setColour (TreeView::backgroundColourId, findColour (backgroundColourId));
tree.setRootItemVisible (false);
tree.setDefaultOpenness (true);
tree.setRootItem (this);
tree.setRootItem (treeItem);
}
KeyMappingEditorComponent::~KeyMappingEditorComponent()
{
mappings->removeChangeListener (this);
tree.setRootItem (0);
}
//==============================================================================
bool KeyMappingEditorComponent::mightContainSubItems()
{
return true;
}
const String KeyMappingEditorComponent::getUniqueName() const
{
return "keys";
}
void KeyMappingEditorComponent::setColours (const Colour& mainBackground,
const Colour& textColour)
{
@@ -323,7 +442,7 @@ void KeyMappingEditorComponent::setColours (const Colour& mainBackground,
void KeyMappingEditorComponent::parentHierarchyChanged()
{
changeListenerCallback (0);
treeItem->changeListenerCallback (0);
}
void KeyMappingEditorComponent::resized()
@@ -343,157 +462,19 @@ void KeyMappingEditorComponent::resized()
tree.setBounds (0, 0, getWidth(), h);
}
void KeyMappingEditorComponent::buttonClicked (Button* button)
{
if (button == &resetButton)
{
if (AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon,
TRANS("Reset to defaults"),
TRANS("Are you sure you want to reset all the key-mappings to their default state?"),
TRANS("Reset")))
{
mappings->resetToDefaultMappings();
}
}
}
void KeyMappingEditorComponent::changeListenerCallback (void*)
{
ScopedPointer <XmlElement> oldOpenness (tree.getOpennessState (true));
clearSubItems();
const StringArray categories (mappings->getCommandManager()->getCommandCategories());
for (int i = 0; i < categories.size(); ++i)
{
const Array <CommandID> commands (mappings->getCommandManager()->getCommandsInCategory (categories[i]));
int count = 0;
for (int j = 0; j < commands.size(); ++j)
if (shouldCommandBeIncluded (commands[j]))
++count;
if (count > 0)
addSubItem (new KeyCategoryTreeViewItem (*this, categories[i]));
}
if (oldOpenness != 0)
tree.restoreOpennessState (*oldOpenness);
}
//==============================================================================
class KeyEntryWindow : public AlertWindow
{
public:
KeyEntryWindow (KeyMappingEditorComponent& owner_)
: AlertWindow (TRANS("New key-mapping"),
TRANS("Please press a key combination now..."),
AlertWindow::NoIcon),
owner (owner_)
{
addButton (TRANS("ok"), 1);
addButton (TRANS("cancel"), 0);
// (avoid return + escape keys getting processed by the buttons..)
for (int i = getNumChildComponents(); --i >= 0;)
getChildComponent (i)->setWantsKeyboardFocus (false);
setWantsKeyboardFocus (true);
grabKeyboardFocus();
}
~KeyEntryWindow()
{
}
bool keyPressed (const KeyPress& key)
{
lastPress = key;
String message (TRANS("Key: ") + owner.getDescriptionForKeyPress (key));
const CommandID previousCommand = owner.getMappings()->findCommandForKeyPress (key);
if (previousCommand != 0)
{
message << "\n\n"
<< TRANS("(Currently assigned to \"")
<< owner.getMappings()->getCommandManager()->getNameOfCommand (previousCommand)
<< "\")";
}
setMessage (message);
return true;
}
bool keyStateChanged (bool)
{
return true;
}
KeyPress lastPress;
juce_UseDebuggingNewOperator
private:
KeyMappingEditorComponent& owner;
KeyEntryWindow (const KeyEntryWindow&);
KeyEntryWindow& operator= (const KeyEntryWindow&);
};
void KeyMappingEditorComponent::assignNewKey (const CommandID commandID, const int index)
{
KeyEntryWindow entryWindow (*this);
if (entryWindow.runModalLoop() != 0)
{
entryWindow.setVisible (false);
if (entryWindow.lastPress.isValid())
{
const CommandID previousCommand = mappings->findCommandForKeyPress (entryWindow.lastPress);
if (previousCommand != 0)
{
if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon,
TRANS("Change key-mapping"),
TRANS("This key is already assigned to the command \"")
+ mappings->getCommandManager()->getNameOfCommand (previousCommand)
+ TRANS("\"\n\nDo you want to re-assign it to this new command instead?"),
TRANS("re-assign"),
TRANS("cancel")))
{
return;
}
}
mappings->removeKeyPress (entryWindow.lastPress);
if (index >= 0)
mappings->removeKeyPress (commandID, index);
mappings->addKeyPress (commandID, entryWindow.lastPress, index);
}
}
}
//==============================================================================
bool KeyMappingEditorComponent::shouldCommandBeIncluded (const CommandID commandID)
{
const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID);
const ApplicationCommandInfo* const ci = mappings.getCommandManager()->getCommandForID (commandID);
return (ci != 0) && ((ci->flags & ApplicationCommandInfo::hiddenFromKeyEditor) == 0);
return ci != 0 && (ci->flags & ApplicationCommandInfo::hiddenFromKeyEditor) == 0;
}
bool KeyMappingEditorComponent::isCommandReadOnly (const CommandID commandID)
{
const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID);
const ApplicationCommandInfo* const ci = mappings.getCommandManager()->getCommandForID (commandID);
return (ci != 0) && ((ci->flags & ApplicationCommandInfo::readOnlyInKeyEditor) != 0);
return ci != 0 && (ci->flags & ApplicationCommandInfo::readOnlyInKeyEditor) != 0;
}
const String KeyMappingEditorComponent::getDescriptionForKeyPress (const KeyPress& key)


+ 18
- 29
src/gui/components/keyboard/juce_KeyMappingEditorComponent.h View File

@@ -38,23 +38,18 @@
@see KeyPressMappingSet
*/
class JUCE_API KeyMappingEditorComponent : public Component,
public TreeViewItem,
public ChangeListener,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
class JUCE_API KeyMappingEditorComponent : public Component
{
public:
//==============================================================================
/** Creates a KeyMappingEditorComponent.
@param mappingSet this is the set of mappings to display and
edit. Make sure the mappings object is not
deleted before this component!
@param showResetToDefaultButton if true, then at the bottom of the
list, the component will include a 'reset to
defaults' button.
@param mappingSet this is the set of mappings to display and edit. Make sure the
mappings object is not deleted before this component!
@param showResetToDefaultButton if true, then at the bottom of the list, the
component will include a 'reset to defaults' button.
*/
KeyMappingEditorComponent (KeyPressMappingSet* mappingSet,
KeyMappingEditorComponent (KeyPressMappingSet& mappingSet,
bool showResetToDefaultButton);
/** Destructor. */
@@ -69,9 +64,8 @@ public:
void setColours (const Colour& mainBackground,
const Colour& textColour);
/** Returns the KeyPressMappingSet that this component is acting upon.
*/
KeyPressMappingSet* getMappings() const throw() { return mappings; }
/** Returns the KeyPressMappingSet that this component is acting upon. */
KeyPressMappingSet& getMappings() const throw() { return mappings; }
//==============================================================================
@@ -120,29 +114,24 @@ public:
void parentHierarchyChanged();
/** @internal */
void resized();
/** @internal */
void changeListenerCallback (void*);
/** @internal */
bool mightContainSubItems();
/** @internal */
const String getUniqueName() const;
/** @internal */
void buttonClicked (Button* button);
juce_UseDebuggingNewOperator
private:
//==============================================================================
friend class KeyMappingTreeViewItem;
friend class KeyCategoryTreeViewItem;
friend class KeyMappingItemComponent;
friend class KeyMappingChangeButton;
KeyPressMappingSet* mappings;
KeyPressMappingSet& mappings;
TreeView tree;
TextButton resetButton;
void assignNewKey (CommandID commandID, int index);
class TopLevelItem;
class ChangeKeyButton;
class MappingItem;
class CategoryItem;
class ItemComponent;
friend class TopLevelItem;
friend class OwnedArray <ChangeKeyButton>;
friend class ScopedPointer<TopLevelItem>;
ScopedPointer<TopLevelItem> treeItem;
KeyMappingEditorComponent (const KeyMappingEditorComponent&);
KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&);


+ 12
- 15
src/gui/components/layout/juce_Viewport.cpp View File

@@ -58,7 +58,7 @@ Viewport::Viewport (const String& componentName)
Viewport::~Viewport()
{
contentHolder.deleteAllChildren();
deleteContentComp();
}
//==============================================================================
@@ -67,15 +67,19 @@ void Viewport::visibleAreaChanged (int, int, int, int)
}
//==============================================================================
void Viewport::deleteContentComp()
{
// This sets the content comp to a null pointer before deleting the old one, in case
// anything tries to use the old one while it's in mid-deletion..
ScopedPointer<Component> oldCompDeleter (contentComp);
contentComp = 0;
}
void Viewport::setViewedComponent (Component* const newViewedComponent)
{
if (contentComp.getComponent() != newViewedComponent)
{
{
ScopedPointer<Component> oldCompDeleter (contentComp);
contentComp = 0;
}
deleteContentComp();
contentComp = newViewedComponent;
if (contentComp != 0)
@@ -89,15 +93,8 @@ void Viewport::setViewedComponent (Component* const newViewedComponent)
}
}
int Viewport::getMaximumVisibleWidth() const
{
return contentHolder.getWidth();
}
int Viewport::getMaximumVisibleHeight() const
{
return contentHolder.getHeight();
}
int Viewport::getMaximumVisibleWidth() const { return contentHolder.getWidth(); }
int Viewport::getMaximumVisibleHeight() const { return contentHolder.getHeight(); }
void Viewport::setViewPosition (const int xPixelsOffset, const int yPixelsOffset)
{


+ 1
- 0
src/gui/components/layout/juce_Viewport.h View File

@@ -264,6 +264,7 @@ private:
ScrollBar horizontalScrollBar;
void updateVisibleArea();
void deleteContentComp();
Viewport (const Viewport&);
Viewport& operator= (const Viewport&);


+ 74
- 91
src/gui/components/menus/juce_PopupMenu.cpp View File

@@ -148,12 +148,17 @@ class PopupMenu::ItemComponent : public Component
{
public:
//==============================================================================
ItemComponent (const PopupMenu::Item& itemInfo_)
ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight)
: itemInfo (itemInfo_),
isHighlighted (false)
{
if (itemInfo.customComp != 0)
addAndMakeVisible (itemInfo.customComp);
int itemW = 80;
int itemH = 16;
getIdealSize (itemW, itemH, standardItemHeight);
setSize (itemW, jlimit (2, 600, itemH));
}
~ItemComponent()
@@ -258,35 +263,68 @@ class PopupMenu::Window : public Component,
{
public:
//==============================================================================
Window()
Window (const PopupMenu& menu, Window* const owner_, const Rectangle<int>& target,
const bool alignToRectangle, const int itemIdThatMustBeVisible,
const int minimumWidth_, const int maximumNumColumns_,
const int standardItemHeight_, const bool dismissOnMouseUp_,
ApplicationCommandManager** const managerOfChosenCommand_,
Component* const componentAttachedTo_)
: Component ("menu"),
owner (0),
owner (owner_),
activeSubMenu (0),
managerOfChosenCommand (0),
minimumWidth (0),
maximumNumColumns (7),
standardItemHeight (0),
managerOfChosenCommand (managerOfChosenCommand_),
componentAttachedTo (componentAttachedTo_),
componentAttachedToOriginal (componentAttachedTo_),
minimumWidth (minimumWidth_),
maximumNumColumns (maximumNumColumns_),
standardItemHeight (standardItemHeight_),
isOver (false),
hasBeenOver (false),
isDown (false),
needsToScroll (false),
dismissOnMouseUp (dismissOnMouseUp_),
hideOnExit (false),
disableMouseMoves (false),
hasAnyJuceCompHadFocus (false),
numColumns (0),
contentHeight (0),
childYOffset (0),
menuCreationTime (Time::getMillisecondCounter()),
timeEnteredCurrentChildComp (0),
scrollAcceleration (1.0)
{
menuCreationTime = lastFocused = lastScroll = Time::getMillisecondCounter();
setWantsKeyboardFocus (true);
lastFocused = lastScroll = menuCreationTime;
setWantsKeyboardFocus (false);
setMouseClickGrabsKeyboardFocus (false);
setAlwaysOnTop (true);
Desktop::getInstance().addGlobalMouseListener (this);
setLookAndFeel (menu.lookAndFeel);
setOpaque (getLookAndFeel().findColour (PopupMenu::backgroundColourId).isOpaque() || ! Desktop::canUseSemiTransparentWindows());
for (int i = 0; i < menu.items.size(); ++i)
{
PopupMenu::ItemComponent* const itemComp = new PopupMenu::ItemComponent (*menu.items.getUnchecked(i), standardItemHeight);
items.add (itemComp);
addAndMakeVisible (itemComp);
itemComp->addMouseListener (this, false);
}
calculateWindowPos (target, alignToRectangle);
setTopLeftPosition (windowPos.getX(), windowPos.getY());
updateYPositions();
if (itemIdThatMustBeVisible != 0)
{
const int y = target.getY() - windowPos.getY();
ensureItemIsVisible (itemIdThatMustBeVisible,
(((unsigned int) y) < (unsigned int) windowPos.getHeight()) ? y : -1);
}
resizeToBestWindowPos();
addToDesktop (ComponentPeer::windowIsTemporary | getLookAndFeel().getMenuWindowFlags());
getActiveWindows().add (this);
Desktop::getInstance().addGlobalMouseListener (this);
}
~Window()
@@ -294,69 +332,26 @@ public:
getActiveWindows().removeValue (this);
Desktop::getInstance().removeGlobalMouseListener (this);
activeSubMenu = 0;
deleteAllChildren();
items.clear();
}
//==============================================================================
static Window* create (const PopupMenu& menu,
const bool dismissOnMouseUp,
bool dismissOnMouseUp,
Window* const owner_,
const Rectangle<int>& target,
const int minimumWidth,
const int maximumNumColumns,
const int standardItemHeight,
const bool alignToRectangle,
const int itemIdThatMustBeVisible,
int minimumWidth,
int maximumNumColumns,
int standardItemHeight,
bool alignToRectangle,
int itemIdThatMustBeVisible,
ApplicationCommandManager** managerOfChosenCommand,
Component* const componentAttachedTo)
Component* componentAttachedTo)
{
if (menu.items.size() > 0)
{
int totalItems = 0;
ScopedPointer <Window> mw (new Window());
mw->setLookAndFeel (menu.lookAndFeel);
mw->setWantsKeyboardFocus (false);
mw->setOpaque (mw->getLookAndFeel().findColour (PopupMenu::backgroundColourId).isOpaque() || ! Desktop::canUseSemiTransparentWindows());
mw->minimumWidth = minimumWidth;
mw->maximumNumColumns = maximumNumColumns;
mw->standardItemHeight = standardItemHeight;
mw->dismissOnMouseUp = dismissOnMouseUp;
for (int i = 0; i < menu.items.size(); ++i)
{
PopupMenu::Item* const item = menu.items.getUnchecked(i);
mw->addItem (*item);
++totalItems;
}
if (totalItems > 0)
{
mw->owner = owner_;
mw->managerOfChosenCommand = managerOfChosenCommand;
mw->componentAttachedTo = componentAttachedTo;
mw->componentAttachedToOriginal = componentAttachedTo;
mw->calculateWindowPos (target, alignToRectangle);
mw->setTopLeftPosition (mw->windowPos.getX(),
mw->windowPos.getY());
mw->updateYPositions();
if (itemIdThatMustBeVisible != 0)
{
const int y = target.getY() - mw->windowPos.getY();
mw->ensureItemIsVisible (itemIdThatMustBeVisible,
(((unsigned int) y) < (unsigned int) mw->windowPos.getHeight()) ? y : -1);
}
mw->resizeToBestWindowPos();
mw->addToDesktop (ComponentPeer::windowIsTemporary
| mw->getLookAndFeel().getMenuWindowFlags());
return mw.release();
}
}
return new Window (menu, owner_, target, alignToRectangle, itemIdThatMustBeVisible,
minimumWidth, maximumNumColumns, standardItemHeight, dismissOnMouseUp,
managerOfChosenCommand, componentAttachedTo);
return 0;
}
@@ -394,19 +389,6 @@ public:
: childYOffset > 0);
}
//==============================================================================
void addItem (const PopupMenu::Item& item)
{
PopupMenu::ItemComponent* const mic = new PopupMenu::ItemComponent (item);
addAndMakeVisible (mic);
int itemW = 80;
int itemH = 16;
mic->getIdealSize (itemW, itemH, standardItemHeight);
mic->setSize (itemW, jlimit (2, 600, itemH));
mic->addMouseListener (this, false);
}
//==============================================================================
// hide this and all sub-comps
void hide (const PopupMenu::Item* const item, const bool makeInvisible)
@@ -610,8 +592,8 @@ public:
scrollAcceleration = jmin (4.0, scrollAcceleration * 1.04);
int amount = 0;
for (int i = 0; i < getNumChildComponents() && amount == 0; ++i)
amount = ((int) scrollAcceleration) * getChildComponent (i)->getHeight();
for (int i = 0; i < items.size() && amount == 0; ++i)
amount = ((int) scrollAcceleration) * items.getUnchecked(i)->getHeight();
alterChildYPos (localMousePos.getY() < PopupMenuSettings::scrollZone ? -amount : amount);
@@ -714,6 +696,7 @@ public:
private:
Window* owner;
OwnedArray <PopupMenu::ItemComponent> items;
Component::SafePointer<PopupMenu::ItemComponent> currentChild;
ScopedPointer <Window> activeSubMenu;
ApplicationCommandManager** managerOfChosenCommand;
@@ -899,13 +882,13 @@ private:
{
int i, colW = 50, colH = 0;
const int numChildren = jmin (getNumChildComponents() - childNum,
(getNumChildComponents() + numColumns - 1) / numColumns);
const int numChildren = jmin (items.size() - childNum,
(items.size() + numColumns - 1) / numColumns);
for (i = numChildren; --i >= 0;)
{
colW = jmax (colW, getChildComponent (childNum + i)->getWidth());
colH += getChildComponent (childNum + i)->getHeight();
colW = jmax (colW, items.getUnchecked (childNum + i)->getWidth());
colH += items.getUnchecked (childNum + i)->getHeight();
}
colW = jmin (maxMenuW / jmax (1, numColumns - 2), colW + PopupMenuSettings::borderSize * 2);
@@ -932,9 +915,9 @@ private:
{
jassert (itemId != 0)
for (int i = getNumChildComponents(); --i >= 0;)
for (int i = items.size(); --i >= 0;)
{
PopupMenu::ItemComponent* const m = static_cast <PopupMenu::ItemComponent*> (getChildComponent (i));
PopupMenu::ItemComponent* const m = items.getUnchecked(i);
if (m != 0
&& m->itemInfo.itemId == itemId
@@ -1029,8 +1012,8 @@ private:
for (int col = 0; col < numColumns; ++col)
{
const int numChildren = jmin (getNumChildComponents() - childNum,
(getNumChildComponents() + numColumns - 1) / numColumns);
const int numChildren = jmin (items.size() - childNum,
(items.size() + numColumns - 1) / numColumns);
const int colW = columnWidths [col];
@@ -1038,7 +1021,7 @@ private:
for (int i = 0; i < numChildren; ++i)
{
Component* const c = getChildComponent (childNum + i);
Component* const c = items.getUnchecked (childNum + i);
c->setBounds (x, y, colW, c->getHeight());
y += c->getHeight();
}
@@ -1187,14 +1170,14 @@ private:
disableTimerUntilMouseMoves();
PopupMenu::ItemComponent* mic = 0;
bool wasLastOne = (currentChild == 0);
const int numItems = getNumChildComponents();
const int numItems = items.size();
for (int i = 0; i < numItems + 1; ++i)
{
int index = (delta > 0) ? i : (numItems - 1 - i);
index = (index + numItems) % numItems;
mic = dynamic_cast <PopupMenu::ItemComponent*> (getChildComponent (index));
mic = items.getUnchecked (index);
if (mic != 0 && (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu())
&& wasLastOne)
@@ -1713,7 +1696,7 @@ bool PopupMenu::MenuItemIterator::next()
isSeparator = item->isSeparator;
isTicked = item->isTicked;
isEnabled = item->active;
isSectionHeader = dynamic_cast <HeaderItemComponent*> ((PopupMenuCustomComponent*) item->customComp) != 0;
isSectionHeader = dynamic_cast <HeaderItemComponent*> (static_cast <PopupMenuCustomComponent*> (item->customComp)) != 0;
isCustomComponent = (! isSectionHeader) && item->customComp != 0;
customColour = item->usesColour ? &(item->textColour) : 0;
customImage = item->image;


+ 1
- 0
src/gui/components/menus/juce_PopupMenu.h View File

@@ -394,6 +394,7 @@ private:
friend class PopupMenuCustomComponent;
friend class MenuBarComponent;
friend class OwnedArray <Item>;
friend class OwnedArray <ItemComponent>;
friend class ScopedPointer <Window>;
OwnedArray <Item> items;


+ 1
- 1
src/gui/components/mouse/juce_MouseInputSource.cpp View File

@@ -85,7 +85,7 @@ public:
const Point<int> relativePos (comp->getLocalPoint (0, screenPos));
// (the contains() call is needed to test for overlapping desktop windows)
if (comp->contains (relativePos.getX(), relativePos.getY()))
if (comp->contains (relativePos))
return comp->getComponentAt (relativePos);
}


+ 81
- 114
src/gui/components/properties/juce_PropertyPanel.cpp View File

@@ -32,52 +32,29 @@ BEGIN_JUCE_NAMESPACE
#include "../../../text/juce_LocalisedStrings.h"
//==============================================================================
class PropertyPanel::PropertyHolderComponent : public Component
{
public:
PropertyHolderComponent()
{
}
~PropertyHolderComponent()
{
deleteAllChildren();
}
void paint (Graphics&)
{
}
void updateLayout (int width);
void refreshAll() const;
private:
PropertyHolderComponent (const PropertyHolderComponent&);
PropertyHolderComponent& operator= (const PropertyHolderComponent&);
};
//==============================================================================
class PropertySectionComponent : public Component
{
public:
PropertySectionComponent (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool open)
const bool sectionIsOpen_)
: Component (sectionTitle),
titleHeight (sectionTitle.isNotEmpty() ? 22 : 0),
isOpen_ (open)
sectionIsOpen (sectionIsOpen_)
{
for (int i = newProperties.size(); --i >= 0;)
propertyComps.addArray (newProperties);
for (int i = propertyComps.size(); --i >= 0;)
{
addAndMakeVisible (newProperties.getUnchecked(i));
newProperties.getUnchecked(i)->refresh();
addAndMakeVisible (propertyComps.getUnchecked(i));
propertyComps.getUnchecked(i)->refresh();
}
}
~PropertySectionComponent()
{
deleteAllChildren();
propertyComps.clear();
}
void paint (Graphics& g)
@@ -90,16 +67,11 @@ public:
{
int y = titleHeight;
for (int i = getNumChildComponents(); --i >= 0;)
for (int i = 0; i < propertyComps.size(); ++i)
{
PropertyComponent* const pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
{
const int prefH = pec->getPreferredHeight();
pec->setBounds (1, y, getWidth() - 2, prefH);
y += prefH;
}
PropertyComponent* const pec = propertyComps.getUnchecked (i);
pec->setBounds (1, y, getWidth() - 2, pec->getPreferredHeight());
y = pec->getBottom();
}
}
@@ -109,13 +81,8 @@ public:
if (isOpen())
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
y += pec->getPreferredHeight();
}
for (int i = propertyComps.size(); --i >= 0;)
y += propertyComps.getUnchecked(i)->getPreferredHeight();
}
return y;
@@ -123,19 +90,13 @@ public:
void setOpen (const bool open)
{
if (isOpen_ != open)
if (sectionIsOpen != open)
{
isOpen_ = open;
sectionIsOpen = open;
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
for (int i = propertyComps.size(); --i >= 0;)
propertyComps.getUnchecked(i)->setVisible (open);
if (pec != 0)
pec->setVisible (open);
}
// (unable to use the syntax findParentComponentOfClass <DragAndDropContainer> () because of a VC6 compiler bug)
PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0);
if (pp != 0)
@@ -145,22 +106,13 @@ public:
bool isOpen() const
{
return isOpen_;
return sectionIsOpen;
}
void refreshAll() const
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
pec->refresh();
}
}
void mouseDown (const MouseEvent&)
{
for (int i = propertyComps.size(); --i >= 0;)
propertyComps.getUnchecked (i)->refresh();
}
void mouseUp (const MouseEvent& e)
@@ -181,45 +133,65 @@ public:
}
private:
OwnedArray <PropertyComponent> propertyComps;
int titleHeight;
bool isOpen_;
bool sectionIsOpen;
PropertySectionComponent (const PropertySectionComponent&);
PropertySectionComponent& operator= (const PropertySectionComponent&);
};
void PropertyPanel::PropertyHolderComponent::updateLayout (const int width)
//==============================================================================
class PropertyPanel::PropertyHolderComponent : public Component
{
int y = 0;
public:
PropertyHolderComponent() {}
for (int i = getNumChildComponents(); --i >= 0;)
void paint (Graphics&) {}
void updateLayout (int width)
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
int y = 0;
if (section != 0)
for (int i = 0; i < sections.size(); ++i)
{
const int prefH = section->getPreferredHeight();
section->setBounds (0, y, width, prefH);
y += prefH;
PropertySectionComponent* const section = sections.getUnchecked(i);
section->setBounds (0, y, width, section->getPreferredHeight());
y = section->getBottom();
}
setSize (width, y);
repaint();
}
setSize (width, y);
repaint();
}
void refreshAll() const
{
for (int i = 0; i < sections.size(); ++i)
sections.getUnchecked(i)->refreshAll();
}
void PropertyPanel::PropertyHolderComponent::refreshAll() const
{
for (int i = getNumChildComponents(); --i >= 0;)
void clear()
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
sections.clear();
}
if (section != 0)
section->refreshAll();
void addSection (PropertySectionComponent* newSection)
{
sections.add (newSection);
addAndMakeVisible (newSection, 0);
}
}
int getNumSections() const throw() { return sections.size(); }
PropertySectionComponent* getSection (const int index) const { return sections [index]; }
private:
OwnedArray<PropertySectionComponent> sections;
PropertyHolderComponent (const PropertyHolderComponent&);
PropertyHolderComponent& operator= (const PropertyHolderComponent&);
};
//==============================================================================
PropertyPanel::PropertyPanel()
@@ -239,7 +211,7 @@ PropertyPanel::~PropertyPanel()
//==============================================================================
void PropertyPanel::paint (Graphics& g)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
{
g.setColour (Colours::black.withAlpha (0.5f));
g.setFont (14.0f);
@@ -257,21 +229,19 @@ void PropertyPanel::resized()
//==============================================================================
void PropertyPanel::clear()
{
if (propertyHolderComponent->getNumChildComponents() > 0)
if (propertyHolderComponent->getNumSections() > 0)
{
propertyHolderComponent->deleteAllChildren();
propertyHolderComponent->clear();
repaint();
}
}
void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty,
newProperties,
true), 0);
propertyHolderComponent->addSection (new PropertySectionComponent (String::empty, newProperties, true));
updatePropHolderLayout();
}
@@ -281,13 +251,10 @@ void PropertyPanel::addSection (const String& sectionTitle,
{
jassert (sectionTitle.isNotEmpty());
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle,
newProperties,
shouldBeOpen), 0);
propertyHolderComponent->addSection (new PropertySectionComponent (sectionTitle, newProperties, shouldBeOpen));
updatePropHolderLayout();
}
@@ -314,11 +281,11 @@ const StringArray PropertyPanel::getSectionNames() const
{
StringArray s;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
PropertySectionComponent* const section = propertyHolderComponent->getSection (i);
if (section != 0 && section->getName().isNotEmpty())
if (section->getName().isNotEmpty())
s.add (section->getName());
}
@@ -329,11 +296,11 @@ bool PropertyPanel::isSectionOpen (const int sectionIndex) const
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
PropertySectionComponent* const section = propertyHolderComponent->getSection (i);
if (section != 0 && section->getName().isNotEmpty())
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
return section->isOpen();
@@ -349,11 +316,11 @@ void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeO
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
PropertySectionComponent* const section = propertyHolderComponent->getSection (i);
if (section != 0 && section->getName().isNotEmpty())
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
@@ -370,11 +337,11 @@ void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool should
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
PropertySectionComponent* const section = propertyHolderComponent->getSection (i);
if (section != 0 && section->getName().isNotEmpty())
if (section->getName().isNotEmpty())
{
if (index == sectionIndex)
{


+ 1
- 0
src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h View File

@@ -66,6 +66,7 @@ public:
of (0, 0).
*/
virtual void setOrigin (int x, int y) = 0;
virtual void addTransform (const AffineTransform& transform) = 0;
virtual bool clipToRectangle (const Rectangle<int>& r) = 0;
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;


+ 6
- 0
src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp View File

@@ -112,6 +112,12 @@ void LowLevelGraphicsPostScriptRenderer::setOrigin (int x, int y)
}
}
void LowLevelGraphicsPostScriptRenderer::addTransform (const AffineTransform& /*transform*/)
{
//xxx
jassertfalse;
}
bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle<int>& r)
{
needToClip = true;


+ 1
- 0
src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h View File

@@ -49,6 +49,7 @@ public:
//==============================================================================
bool isVectorDevice() const;
void setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);
bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion);


+ 178
- 76
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp View File

@@ -830,19 +830,17 @@ private:
//==============================================================================
void render4PixelAverage (PixelRGB* const dest, const uint8* src, const int subPixelX, const int subPixelY) throw()
{
uint32 c[4] = { 256 * 128, 256 * 128, 256 * 128, 256 * 128 };
uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 };
uint32 weight = (256 - subPixelX) * (256 - subPixelY);
c[0] += weight * src[0];
c[1] += weight * src[1];
c[2] += weight * src[2];
c[3] += weight * src[3];
weight = subPixelX * (256 - subPixelY);
c[0] += weight * src[4];
c[1] += weight * src[5];
c[2] += weight * src[6];
c[3] += weight * src[7];
c[0] += weight * src[3];
c[1] += weight * src[4];
c[2] += weight * src[5];
src += this->srcData.lineStride;
@@ -850,60 +848,56 @@ private:
c[0] += weight * src[0];
c[1] += weight * src[1];
c[2] += weight * src[2];
c[3] += weight * src[3];
weight = subPixelX * subPixelY;
c[0] += weight * src[4];
c[1] += weight * src[5];
c[2] += weight * src[6];
c[3] += weight * src[7];
c[0] += weight * src[3];
c[1] += weight * src[4];
c[2] += weight * src[5];
dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 16),
(uint8) (c[PixelARGB::indexR] >> 16),
(uint8) (c[PixelARGB::indexG] >> 16),
(uint8) (c[PixelARGB::indexB] >> 16));
dest->setARGB ((uint8) 255,
(uint8) (c[PixelRGB::indexR] >> 16),
(uint8) (c[PixelRGB::indexG] >> 16),
(uint8) (c[PixelRGB::indexB] >> 16));
}
void render2PixelAverageX (PixelRGB* const dest, const uint8* src, const int subPixelX, const int alpha) throw()
void render2PixelAverageX (PixelRGB* const dest, const uint8* src, const int subPixelX, const int /*alpha*/) throw()
{
uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 };
uint32 c[3] = { 128, 128, 128 };
uint32 weight = (256 - subPixelX) * alpha;
uint32 weight = (256 - subPixelX);
c[0] += weight * src[0];
c[1] += weight * src[1];
c[2] += weight * src[2];
weight = subPixelX * alpha;
c[0] += weight * src[3];
c[1] += weight * src[4];
c[2] += weight * src[5];
c[0] += subPixelX * src[3];
c[1] += subPixelX * src[4];
c[2] += subPixelX * src[5];
dest->setARGB ((uint8) 255,
(uint8) (c[PixelRGB::indexR] >> 16),
(uint8) (c[PixelRGB::indexG] >> 16),
(uint8) (c[PixelRGB::indexB] >> 16));
(uint8) (c[PixelRGB::indexR] >> 8),
(uint8) (c[PixelRGB::indexG] >> 8),
(uint8) (c[PixelRGB::indexB] >> 8));
}
void render2PixelAverageY (PixelRGB* const dest, const uint8* src, const int subPixelY, const int alpha) throw()
void render2PixelAverageY (PixelRGB* const dest, const uint8* src, const int subPixelY, const int /*alpha*/) throw()
{
uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 };
uint32 c[3] = { 128, 128, 128 };
uint32 weight = (256 - subPixelY) * alpha;
uint32 weight = (256 - subPixelY);
c[0] += weight * src[0];
c[1] += weight * src[1];
c[2] += weight * src[2];
src += this->srcData.lineStride;
weight = subPixelY * alpha;
c[0] += weight * src[0];
c[1] += weight * src[1];
c[2] += weight * src[2];
c[0] += subPixelY * src[0];
c[1] += subPixelY * src[1];
c[2] += subPixelY * src[2];
dest->setARGB ((uint8) 255,
(uint8) (c[PixelRGB::indexR] >> 16),
(uint8) (c[PixelRGB::indexG] >> 16),
(uint8) (c[PixelRGB::indexB] >> 16));
(uint8) (c[PixelRGB::indexR] >> 8),
(uint8) (c[PixelRGB::indexG] >> 8),
(uint8) (c[PixelRGB::indexB] >> 8));
}
//==============================================================================
@@ -1796,38 +1790,67 @@ class LowLevelGraphicsSoftwareRenderer::SavedState
public:
SavedState (const Rectangle<int>& clip_, const int xOffset_, const int yOffset_)
: clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)),
xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality)
xOffset (xOffset_), yOffset (yOffset_), isOnlyTranslated (true), interpolationQuality (Graphics::mediumResamplingQuality)
{
}
SavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_)
: clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)),
xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality)
xOffset (xOffset_), yOffset (yOffset_), isOnlyTranslated (true), interpolationQuality (Graphics::mediumResamplingQuality)
{
}
SavedState (const SavedState& other)
: clip (other.clip), xOffset (other.xOffset), yOffset (other.yOffset), font (other.font),
fillType (other.fillType), interpolationQuality (other.interpolationQuality)
: clip (other.clip), complexTransform (other.complexTransform), xOffset (other.xOffset), yOffset (other.yOffset),
isOnlyTranslated (other.isOnlyTranslated), font (other.font), fillType (other.fillType), interpolationQuality (other.interpolationQuality)
{
}
~SavedState()
void setOrigin (const int x, const int y) throw()
{
if (isOnlyTranslated)
{
xOffset += x;
yOffset += y;
}
else
{
complexTransform = getTransformWith (AffineTransform::translation ((float) x, (float) y));
}
}
void setOrigin (const int x, const int y) throw()
void addTransform (const AffineTransform& t)
{
xOffset += x;
yOffset += y;
if ((! isOnlyTranslated)
|| (! t.isOnlyTranslation())
|| (int) (t.getTranslationX() * 256.0f) != 0
|| (int) (t.getTranslationY() * 256.0f) != 0)
{
complexTransform = getTransformWith (t);
isOnlyTranslated = false;
}
else
{
xOffset += (int) t.getTranslationX();
yOffset += (int) t.getTranslationY();
}
}
bool clipToRectangle (const Rectangle<int>& r)
{
if (clip != 0)
{
cloneClipIfMultiplyReferenced();
clip = clip->clipToRectangle (r.translated (xOffset, yOffset));
if (isOnlyTranslated)
{
cloneClipIfMultiplyReferenced();
clip = clip->clipToRectangle (r.translated (xOffset, yOffset));
}
else
{
Path p;
p.addRectangle (r);
clipToPath (p, AffineTransform::identity);
}
}
return clip != 0;
@@ -1837,11 +1860,17 @@ public:
{
if (clip != 0)
{
cloneClipIfMultiplyReferenced();
RectangleList offsetList (r);
offsetList.offsetAll (xOffset, yOffset);
clip = clip->clipToRectangleList (offsetList);
if (isOnlyTranslated)
{
cloneClipIfMultiplyReferenced();
RectangleList offsetList (r);
offsetList.offsetAll (xOffset, yOffset);
clip = clip->clipToRectangleList (offsetList);
}
else
{
clipToPath (r.toPath(), AffineTransform::identity);
}
}
return clip != 0;
@@ -1851,8 +1880,17 @@ public:
{
if (clip != 0)
{
cloneClipIfMultiplyReferenced();
clip = clip->excludeClipRectangle (r.translated (xOffset, yOffset));
if (isOnlyTranslated)
{
cloneClipIfMultiplyReferenced();
clip = clip->excludeClipRectangle (r.translated (xOffset, yOffset));
}
else
{
RectangleList all (getClipBounds());
all.subtract (r);
return clipToRectangleList (all);
}
}
return clip != 0;
@@ -1863,7 +1901,7 @@ public:
if (clip != 0)
{
cloneClipIfMultiplyReferenced();
clip = clip->clipToPath (p, transform.translated ((float) xOffset, (float) yOffset));
clip = clip->clipToPath (p, getTransformWith (transform));
}
}
@@ -1874,7 +1912,7 @@ public:
if (image.hasAlphaChannel())
{
cloneClipIfMultiplyReferenced();
clip = clip->clipToImageAlpha (image, t.translated ((float) xOffset, (float) yOffset),
clip = clip->clipToImageAlpha (image, getTransformWith (t),
interpolationQuality != Graphics::lowResamplingQuality);
}
else
@@ -1888,12 +1926,28 @@ public:
bool clipRegionIntersects (const Rectangle<int>& r) const
{
return clip != 0 && clip->clipRegionIntersects (r.translated (xOffset, yOffset));
if (clip != 0)
{
if (isOnlyTranslated)
return clip->clipRegionIntersects (r.translated (xOffset, yOffset));
else
return getClipBounds().intersects (r);
}
return false;
}
const Rectangle<int> getClipBounds() const
{
return clip == 0 ? Rectangle<int>() : clip->getClipBounds().translated (-xOffset, -yOffset);
if (clip != 0)
{
if (isOnlyTranslated)
return clip->getClipBounds().translated (-xOffset, -yOffset);
else
return clip->getClipBounds().toFloat().transformed (getTransform().inverted()).getSmallestIntegerContainer();
}
return Rectangle<int>();
}
//==============================================================================
@@ -1901,18 +1955,27 @@ public:
{
if (clip != 0)
{
if (fillType.isColour())
if (isOnlyTranslated)
{
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated (xOffset, yOffset), fillType.colour.getPixelARGB(), replaceContents);
if (fillType.isColour())
{
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated (xOffset, yOffset), fillType.colour.getPixelARGB(), replaceContents);
}
else
{
const Rectangle<int> totalClip (clip->getClipBounds());
const Rectangle<int> clipped (totalClip.getIntersection (r.translated (xOffset, yOffset)));
if (! clipped.isEmpty())
fillShape (image, new SoftwareRendererClasses::ClipRegion_RectangleList (clipped), false);
}
}
else
{
const Rectangle<int> totalClip (clip->getClipBounds());
const Rectangle<int> clipped (totalClip.getIntersection (r.translated (xOffset, yOffset)));
if (! clipped.isEmpty())
fillShape (image, new SoftwareRendererClasses::ClipRegion_RectangleList (clipped), false);
Path p;
p.addRectangle (r);
fillPath (image, p, AffineTransform::identity);
}
}
}
@@ -1921,18 +1984,27 @@ public:
{
if (clip != 0)
{
if (fillType.isColour())
if (isOnlyTranslated)
{
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated ((float) xOffset, (float) yOffset), fillType.colour.getPixelARGB());
if (fillType.isColour())
{
Image::BitmapData destData (image, true);
clip->fillRectWithColour (destData, r.translated ((float) xOffset, (float) yOffset), fillType.colour.getPixelARGB());
}
else
{
const Rectangle<float> totalClip (clip->getClipBounds().toFloat());
const Rectangle<float> clipped (totalClip.getIntersection (r.translated ((float) xOffset, (float) yOffset)));
if (! clipped.isEmpty())
fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clipped), false);
}
}
else
{
const Rectangle<float> totalClip (clip->getClipBounds().toFloat());
const Rectangle<float> clipped (totalClip.getIntersection (r.translated ((float) xOffset, (float) yOffset)));
if (! clipped.isEmpty())
fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clipped), false);
Path p;
p.addRectangle (r);
fillPath (image, p, AffineTransform::identity);
}
}
}
@@ -1940,11 +2012,13 @@ public:
void fillPath (Image& image, const Path& path, const AffineTransform& transform)
{
if (clip != 0)
fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clip->getClipBounds(), path, transform.translated ((float) xOffset, (float) yOffset)), false);
fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clip->getClipBounds(), path, getTransformWith (transform)), false);
}
void fillEdgeTable (Image& image, const EdgeTable& edgeTable, const float x, const int y)
{
jassert (isOnlyTranslated);
if (clip != 0)
{
SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable);
@@ -1970,7 +2044,7 @@ public:
ColourGradient g2 (*(fillType.gradient));
g2.multiplyOpacity (fillType.getOpacity());
AffineTransform transform (fillType.transform.translated (xOffset - 0.5f, yOffset - 0.5f));
AffineTransform transform (getTransformWith (fillType.transform).translated (-0.5f, -0.5f));
const bool isIdentity = transform.isOnlyTranslation();
@@ -1998,7 +2072,7 @@ public:
//==============================================================================
void renderImage (Image& destImage, const Image& sourceImage, const AffineTransform& t, const SoftwareRendererClasses::ClipRegionBase* const tiledFillClipRegion)
{
const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset));
const AffineTransform transform (getTransformWith (t));
const Image::BitmapData destData (destImage, true);
const Image::BitmapData srcData (sourceImage, false);
@@ -2055,7 +2129,14 @@ public:
//==============================================================================
SoftwareRendererClasses::ClipRegionBase::Ptr clip;
private:
AffineTransform complexTransform;
int xOffset, yOffset;
public:
bool isOnlyTranslated;
Font font;
FillType fillType;
Graphics::ResamplingQuality interpolationQuality;
@@ -2067,6 +2148,22 @@ private:
clip = clip->clone();
}
const AffineTransform getTransform() const
{
if (isOnlyTranslated)
return AffineTransform::translation ((float) xOffset, (float) yOffset);
return complexTransform;
}
const AffineTransform getTransformWith (const AffineTransform& userTransform) const
{
if (isOnlyTranslated)
return userTransform.translated ((float) xOffset, (float) yOffset);
return userTransform.followedBy (complexTransform);
}
SavedState& operator= (const SavedState&);
};
@@ -2100,6 +2197,11 @@ void LowLevelGraphicsSoftwareRenderer::setOrigin (int x, int y)
currentState->setOrigin (x, y);
}
void LowLevelGraphicsSoftwareRenderer::addTransform (const AffineTransform& transform)
{
currentState->addTransform (transform);
}
bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle<int>& r)
{
return currentState->clipToRectangle (r);
@@ -2353,7 +2455,7 @@ void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineT
{
Font& f = currentState->font;
if (transform.isOnlyTranslation())
if (transform.isOnlyTranslation() && currentState->isOnlyTranslated)
{
GlyphCache::getInstance()->drawGlyph (*currentState, image, f, glyphNumber,
transform.getTranslationX(),


+ 1
- 0
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h View File

@@ -49,6 +49,7 @@ public:
//==============================================================================
void setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);
bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion);


+ 9
- 21
src/native/linux/juce_linux_Windowing.cpp View File

@@ -946,31 +946,19 @@ public:
bool contains (const Point<int>& position, bool trueIfInAChildWindow) const
{
int x = position.getX();
int y = position.getY();
if (((unsigned int) x) >= (unsigned int) ww
|| ((unsigned int) y) >= (unsigned int) wh)
if (((unsigned int) position.getX()) >= (unsigned int) ww
|| ((unsigned int) position.getY()) >= (unsigned int) wh)
return false;
bool inFront = false;
for (int i = 0; i < Desktop::getInstance().getNumComponents(); ++i)
for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
{
Component* const c = Desktop::getInstance().getComponent (i);
if (inFront)
{
if (c->contains (x + wx - c->getScreenX(),
y + wy - c->getScreenY()))
{
return false;
}
}
else if (c == getComponent())
{
inFront = true;
}
if (c == getComponent())
break;
if (c->contains (position + Point<int> (wx, wy) - c->getScreenPosition()))
return false;
}
if (trueIfInAChildWindow)
@@ -988,7 +976,7 @@ public:
return false;
}
if (! XTranslateCoordinates (display, windowH, windowH, x, y, &wx, &wy, &child))
if (! XTranslateCoordinates (display, windowH, windowH, position.getX(), position.getY(), &wx, &wy, &child))
return false;
return child == None;


+ 10
- 0
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -180,6 +180,16 @@ public:
lastClipRect.translate (-x, -y);
}
void addTransform (const AffineTransform& transform)
{
applyTransform (AffineTransform::scale (1.0f, -1.0f)
.translated (0, flipHeight)
.followedBy (transform)
.translated (0, -flipHeight)
.scaled (1.0f, -1.0f));
lastClipRectIsValid = false;
}
bool clipToRectangle (const Rectangle<int>& r)
{
CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()));


+ 6
- 0
src/native/windows/juce_win32_Direct2DGraphicsContext.cpp View File

@@ -119,6 +119,12 @@ public:
currentState->origin.addXY (x, y);
}
void addTransform (const AffineTransform& transform)
{
//xxx todo
jassertfalse;
}
bool clipToRectangle (const Rectangle<int>& r)
{
currentState->clipToRectangle (r);


Loading…
Cancel
Save