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(); loadData();
// Create our table component and add it to this component.. // 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 // 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.. // Add some columns to the table header, based on the column list in our database..
forEachXmlChildElement (*columnList, columnXml) 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.. // 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 // 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() ~TableDemoComponent()
@@ -119,7 +120,7 @@ public:
DemoDataSorter sorter (getAttributeNameForColumnId (newSortColumnId), isForwards); DemoDataSorter sorter (getAttributeNameForColumnId (newSortColumnId), isForwards);
dataList->sortChildElements (sorter); dataList->sortChildElements (sorter);
table->updateContent();
table.updateContent();
} }
} }
@@ -190,14 +191,14 @@ public:
void resized() void resized()
{ {
// position our table with a gap around its edge // position our table with a gap around its edge
table->setBoundsInset (BorderSize (8));
table.setBoundsInset (BorderSize (8));
} }
//============================================================================== //==============================================================================
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
private: private:
ScopedPointer<TableListBox> table; // the table component itself
TableListBox table; // the table component itself
Font font; Font font;
ScopedPointer<XmlElement> demoData; // This is the XML document loaded from the embedded file "demo table data.xml" 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) else if (pageName == keysPage)
{ {
return new KeyMappingEditorComponent (commandManager->getKeyMappings(), true);
return new KeyMappingEditorComponent (*commandManager->getKeyMappings(), true);
} }
else if (pageName == aboutPage) 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); delButton->setEnabled (false);
addAndMakeVisible (listBox = new TableListBox (String::empty, this)); 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->setColour (ListBox::outlineColourId, Colours::darkgrey);
listBox->setOutlineThickness (1); 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_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52 #define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90


/** Current Juce version number. /** Current Juce version number.


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


Never override this method! Use hitTest to create custom hit regions. 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 @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 part of the component isn't clipped by its parent component. Note
that this won't take into account any overlapping sibling components that this won't take into account any overlapping sibling components
which might be in the way - for that, see reallyContains() which might be in the way - for that, see reallyContains()
@see hitTest, reallyContains, getComponentAt @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 /** Returns true if a given point lies in this component, taking any overlapping
siblings into account. siblings into account.
@@ -27914,6 +27913,9 @@ public:
/** If the component is valid, this deletes it and sets this pointer to null. */ /** If the component is valid, this deletes it and sets this pointer to null. */
void deleteAndZero() { delete comp; jassert (comp == 0); } 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 juce_UseDebuggingNewOperator


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


@@ -28067,9 +28067,14 @@ private:
// implement its methods instead of this Component method). // implement its methods instead of this Component method).
virtual void filesDropped (const StringArray&, int, int) {} 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 (const Component&);
Component& operator= (const Component&); Component& operator= (const Component&);


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


void updateVisibleArea(); void updateVisibleArea();
void deleteContentComp();


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


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


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


friend class ItemDragAndDropOverlayComponent; friend class ItemDragAndDropOverlayComponent;
static const char* const toolbarDragDescriptor; 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 The model pointer passed-in can be null, in which case you can set it later
with setModel(). with setModel().
*/ */
TableListBox (const String& componentName,
TableListBoxModel* model);
TableListBox (const String& componentName = String::empty,
TableListBoxModel* model = 0);


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


/** Returns the header component being used in this table. */ /** 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. /** Changes the height of the table header component.
@see getHeaderHeight @see getHeaderHeight
@@ -52609,23 +52616,18 @@ private:


@see KeyPressMappingSet @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: public:


/** Creates a KeyMappingEditorComponent. /** 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); bool showResetToDefaultButton);


/** Destructor. */ /** Destructor. */
@@ -52639,9 +52641,8 @@ public:
void setColours (const Colour& mainBackground, void setColours (const Colour& mainBackground,
const Colour& textColour); 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. /** Can be overridden if some commands need to be excluded from the list.


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


juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


private: private:


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

KeyPressMappingSet* mappings;
KeyPressMappingSet& mappings;
TreeView tree; TreeView tree;
TextButton resetButton; 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 (const KeyMappingEditorComponent&);
KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&); KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&);
@@ -60143,6 +60139,7 @@ public:
of (0, 0). of (0, 0).
*/ */
virtual void setOrigin (int x, int y) = 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 clipToRectangle (const Rectangle<int>& r) = 0;
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0; virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0;
@@ -60204,6 +60201,7 @@ public:


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


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


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


bool clipToRectangle (const Rectangle<int>& r); bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion); 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_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52 #define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 89
#define JUCE_BUILDNUMBER 90
/** Current Juce version number. /** 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), isButtonDown (false),
separatorPending (false), separatorPending (false),
menuActive (false), menuActive (false),
label (0)
noChoicesMessage (TRANS("(no choices)"))
{ {
noChoicesMessage = TRANS("(no choices)");
setRepaintsOnMouseActivity (true); setRepaintsOnMouseActivity (true);
lookAndFeelChanged(); lookAndFeelChanged();
currentId.addListener (this); currentId.addListener (this);
} }
@@ -58,7 +55,6 @@ ComboBox::~ComboBox()
PopupMenu::dismissAllActiveMenus(); PopupMenu::dismissAllActiveMenus();
label = 0; label = 0;
deleteAllChildren();
} }
//============================================================================== //==============================================================================
@@ -429,30 +425,33 @@ void ComboBox::lookAndFeelChanged()
{ {
repaint(); 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(); resized();
} }
@@ -465,27 +464,23 @@ void ComboBox::colourChanged()
//============================================================================== //==============================================================================
bool ComboBox::keyPressed (const KeyPress& key) 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)); 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)); setSelectedItemIndex (jmin (getSelectedItemIndex() + 1, getNumItems() - 1));
used = true;
return true;
} }
else if (key.isKeyCode (KeyPress::returnKey)) else if (key.isKeyCode (KeyPress::returnKey))
{ {
showPopup(); showPopup();
used = true;
return true;
} }
return used;
return false;
} }
bool ComboBox::keyStateChanged (const bool isKeyDown) 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*) void ComboBox::labelTextChanged (Label*)
{ {
triggerAsyncUpdate(); triggerAsyncUpdate();
@@ -582,11 +569,8 @@ void ComboBox::mouseDown (const MouseEvent& e)
isButtonDown = isEnabled(); isButtonDown = isEnabled();
if (isButtonDown
&& (e.eventComponent == this || ! label->isEditable()))
{
if (isButtonDown && (e.eventComponent == this || ! label->isEditable()))
showPopup(); showPopup();
}
} }
void ComboBox::mouseDrag (const MouseEvent& e) 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 if (editSingleClick
&& e.mouseWasClicked() && e.mouseWasClicked()
&& contains (e.x, e.y)
&& contains (e.getPosition())
&& ! e.mods.isPopupMenu()) && ! e.mods.isPopupMenu())
{ {
showEditor(); 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, class TableListRowComp : public Component,
public TooltipClient public TooltipClient
{ {
public: public:
TableListRowComp (TableListBox& owner_) TableListRowComp (TableListBox& owner_)
: owner (owner_),
row (-1),
isSelected (false)
: owner (owner_), row (-1), isSelected (false)
{ {
} }
~TableListRowComp()
{
deleteAllChildren();
}
void paint (Graphics& g) void paint (Graphics& g)
{ {
TableListBoxModel* const model = owner.getModel(); TableListBoxModel* const model = owner.getModel();
if (model != 0) if (model != 0)
{ {
const TableHeaderComponent* const header = owner.getHeader();
model->paintRowBackground (g, row, getWidth(), getHeight(), isSelected); 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) 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.saveState();
g.reduceClipRegion (columnRect); g.reduceClipRegion (columnRect);
g.setOrigin (columnRect.getX(), 0); g.setOrigin (columnRect.getX(), 0);
model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected); model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected);
g.restoreState(); g.restoreState();
} }
} }
@@ -89,79 +75,66 @@ public:
void update (const int newRow, const bool isNowSelected) void update (const int newRow, const bool isNowSelected)
{ {
jassert (newRow >= 0);
if (newRow != row || isNowSelected != isSelected) if (newRow != row || isNowSelected != isSelected)
{ {
row = newRow; row = newRow;
isSelected = isNowSelected; isSelected = isNowSelected;
repaint(); 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 else
{ {
columnsWithComponents.clear();
deleteAllChildren();
columnComponents.clear();
} }
} }
void resized() 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) void mouseDown (const MouseEvent& e)
@@ -175,7 +148,7 @@ public:
{ {
owner.selectRowsBasedOnModifierKeys (row, e.mods); 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) if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellClicked (row, columnId, e); owner.getModel()->cellClicked (row, columnId, e);
@@ -212,7 +185,7 @@ public:
{ {
owner.selectRowsBasedOnModifierKeys (row, e.mods); 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) if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellClicked (row, columnId, e); owner.getModel()->cellClicked (row, columnId, e);
@@ -221,7 +194,7 @@ public:
void mouseDoubleClick (const MouseEvent& e) 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) if (columnId != 0 && owner.getModel() != 0)
owner.getModel()->cellDoubleClicked (row, columnId, e); owner.getModel()->cellDoubleClicked (row, columnId, e);
@@ -229,7 +202,7 @@ public:
const String getTooltip() 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) if (columnId != 0 && owner.getModel() != 0)
return owner.getModel()->getCellTooltip (row, columnId); return owner.getModel()->getCellTooltip (row, columnId);
@@ -239,24 +212,16 @@ public:
Component* findChildComponentForColumn (const int columnId) const 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 juce_UseDebuggingNewOperator
private: private:
TableListBox& owner; TableListBox& owner;
OwnedArray<Component> columnComponents;
int row; int row;
bool isSelected, isDragging, selectRowOnMouseUp; bool isSelected, isDragging, selectRowOnMouseUp;
BigInteger columnsWithComponents;
TableListRowComp (const TableListRowComp&); TableListRowComp (const TableListRowComp&);
TableListRowComp& operator= (const TableListRowComp&); TableListRowComp& operator= (const TableListRowComp&);
@@ -277,7 +242,7 @@ public:
if (owner.isAutoSizeMenuOptionShown()) if (owner.isAutoSizeMenuOptionShown())
{ {
menu.addItem (autoSizeColumnId, TRANS("Auto-size this column"), columnIdClicked != 0); 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(); menu.addSeparator();
} }
@@ -286,17 +251,11 @@ public:
void reactToMenuItem (int menuReturnId, int columnIdClicked) 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; 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 const bool relativeToComponentTopLeft) const
{ {
Rectangle<int> headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true))); Rectangle<int> headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true)));
@@ -384,10 +342,9 @@ const Rectangle<int> TableListBox::getCellPosition (const int columnId,
if (relativeToComponentTopLeft) if (relativeToComponentTopLeft)
headerCell.translate (header->getX(), 0); 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 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) 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 The model pointer passed-in can be null, in which case you can set it later
with setModel(). with setModel().
*/ */
TableListBox (const String& componentName,
TableListBoxModel* model);
TableListBox (const String& componentName = String::empty,
TableListBoxModel* model = 0);
/** Destructor. */ /** Destructor. */
~TableListBox(); ~TableListBox();
@@ -224,7 +224,7 @@ public:
//============================================================================== //==============================================================================
/** Returns the header component being used in this table. */ /** 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. /** Changes the height of the table header component.
@see getHeaderHeight @see getHeaderHeight


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

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


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

@@ -294,12 +294,12 @@ public:
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
private: private:
Button* missingItemsButton;
ScopedPointer<Button> missingItemsButton;
bool vertical, isEditingActive; bool vertical, isEditingActive;
ToolbarItemStyle toolbarStyle; ToolbarItemStyle toolbarStyle;
class MissingItemsComponent; class MissingItemsComponent;
friend class MissingItemsComponent; friend class MissingItemsComponent;
Array <ToolbarItemComponent*> items;
OwnedArray <ToolbarItemComponent> items;
friend class ItemDragAndDropOverlayComponent; friend class ItemDragAndDropOverlayComponent;
static const char* const toolbarDragDescriptor; 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 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> 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); jassert (directParent != 0);
if (directParent == parent) if (directParent == parent)
return convertFromParentSpace (target, coordInParent); return convertFromParentSpace (target, coordInParent);
return convertFromParentSpace (target, convertFromDistantParentSpace (parent, directParent, coordInParent));
return convertFromParentSpace (target, convertFromDistantParentSpace (parent, *directParent, coordInParent));
} }
template <typename Type> template <typename Type>
@@ -827,7 +834,7 @@ namespace CoordinateHelpers
return p; return p;
if (source->isParentOf (target)) if (source->isParentOf (target))
return convertFromDistantParentSpace (source, target, p);
return convertFromDistantParentSpace (source, *target, p);
if (source->isOnDesktop()) if (source->isOnDesktop())
{ {
@@ -836,7 +843,7 @@ namespace CoordinateHelpers
} }
else else
{ {
p = convertToParentSpace (source, p);
p = convertToParentSpace (*source, p);
source = source->getParentComponent(); source = source->getParentComponent();
} }
} }
@@ -850,12 +857,24 @@ namespace CoordinateHelpers
if (topLevelComp->isOnDesktop()) if (topLevelComp->isOnDesktop())
p = topLevelComp->getPeer()->globalToLocal (p); p = topLevelComp->getPeer()->globalToLocal (p);
else else
p = convertFromParentSpace (topLevelComp, p);
p = convertFromParentSpace (*topLevelComp, p);
if (topLevelComp == target) if (topLevelComp == target)
return p; 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;) 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; return true;
}
} }
} }
@@ -1129,70 +1144,50 @@ void Component::getInterceptsMouseClicks (bool& allowsClicksOnThisComponent,
allowsClicksOnChildComponents = flags.allowChildMouseClicksFlag; 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) if (parentComponent_ != 0)
{ {
return parentComponent_->contains (x + getX(),
y + getY());
return parentComponent_->contains (CoordinateHelpers::convertToParentSpace (*this, point));
} }
else if (flags.hasHeavyweightPeerFlag) else if (flags.hasHeavyweightPeerFlag)
{ {
const ComponentPeer* const peer = getPeer(); const ComponentPeer* const peer = getPeer();
if (peer != 0) if (peer != 0)
return peer->contains (Point<int> (x, y), true);
return peer->contains (point, true);
} }
} }
return false; 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) 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;) 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; return this;
@@ -1201,6 +1196,11 @@ Component* Component::getComponentAt (const int x, const int y)
return 0; 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) void Component::addChildComponent (Component* const child, int zOrder)
{ {
@@ -1925,27 +1925,6 @@ const Rectangle<int> Component::getParentOrMainMonitorBounds() const
: Desktop::getInstance().getMainMonitorArea(); : 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, void Component::clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect,
const int deltaX, const int deltaY) const 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 void Component::getVisibleArea (RectangleList& result, const bool includeSiblings) const
{ {
result.clear(); result.clear();
const Rectangle<int> unclipped (getUnclippedArea());
const Rectangle<int> unclipped (CoordinateHelpers::getUnclippedArea (*this));
if (! unclipped.isEmpty()) 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. 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 @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 part of the component isn't clipped by its parent component. Note
that this won't take into account any overlapping sibling components that this won't take into account any overlapping sibling components
which might be in the way - for that, see reallyContains() which might be in the way - for that, see reallyContains()
@see hitTest, reallyContains, getComponentAt @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 /** Returns true if a given point lies in this component, taking any overlapping
siblings into account. siblings into account.
@@ -1949,6 +1948,9 @@ public:
/** If the component is valid, this deletes it and sets this pointer to null. */ /** If the component is valid, this deletes it and sets this pointer to null. */
void deleteAndZero() { delete comp; jassert (comp == 0); } 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 juce_UseDebuggingNewOperator
@@ -2097,8 +2099,6 @@ private:
const Rectangle<int>& clipRect, const Component* const compToAvoid) const; const Rectangle<int>& clipRect, const Component* const compToAvoid) const;
void clipObscuredRegions (Graphics& g, const Rectangle<int>& clipRect, int deltaX, int deltaY) 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(); void sendVisibilityChangeMessage();
const Rectangle<int> getParentOrMainMonitorBounds() const; const Rectangle<int> getParentOrMainMonitorBounds() const;
@@ -2109,9 +2109,14 @@ private:
// implement its methods instead of this Component method). // implement its methods instead of this Component method).
virtual void filesDropped (const StringArray&, int, int) {} 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 (const Component&);
Component& operator= (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)); 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: 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), : Button (keyName),
owner (owner_), owner (owner_),
commandID (commandID_), commandID (commandID_),
@@ -75,21 +75,16 @@ public:
m.addSeparator(); m.addSeparator();
m.addItem (2, TRANS("remove this key-mapping")); 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 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 juce_UseDebuggingNewOperator
private: private:
@@ -113,43 +190,37 @@ private:
const CommandID commandID; const CommandID commandID;
const int keyNum; 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: public:
KeyMappingItemComponent (KeyMappingEditorComponent& owner_, const CommandID commandID_)
ItemComponent (KeyMappingEditorComponent& owner_, const CommandID commandID_)
: owner (owner_), commandID (commandID_) : owner (owner_), commandID (commandID_)
{ {
setInterceptsMouseClicks (false, true); setInterceptsMouseClicks (false, true);
const bool isReadOnly = owner.isCommandReadOnly (commandID); 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) 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) void paint (Graphics& g)
@@ -157,7 +228,7 @@ public:
g.setFont (getHeight() * 0.7f); g.setFont (getHeight() * 0.7f);
g.setColour (findColour (KeyMappingEditorComponent::textColourId)); 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(), 4, 0, jmax (40, getChildComponent (0)->getX() - 5), getHeight(),
Justification::centredLeft, true); Justification::centredLeft, true);
} }
@@ -166,33 +237,34 @@ public:
{ {
int x = getWidth() - 4; 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 juce_UseDebuggingNewOperator
private: private:
KeyMappingEditorComponent& owner; KeyMappingEditorComponent& owner;
OwnedArray<ChangeKeyButton> keyChangeButtons;
const CommandID commandID; 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: public:
KeyMappingTreeViewItem (KeyMappingEditorComponent& owner_, const CommandID commandID_)
MappingItem (KeyMappingEditorComponent& owner_, const CommandID commandID_)
: owner (owner_), commandID (commandID_) : owner (owner_), commandID (commandID_)
{ {
} }
@@ -203,7 +275,7 @@ public:
Component* createItemComponent() Component* createItemComponent()
{ {
return new KeyMappingItemComponent (owner, commandID);
return new ItemComponent (owner, commandID);
} }
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
@@ -212,16 +284,16 @@ private:
KeyMappingEditorComponent& owner; KeyMappingEditorComponent& owner;
const CommandID commandID; 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: public:
KeyCategoryTreeViewItem (KeyMappingEditorComponent& owner_, const String& name)
CategoryItem (KeyMappingEditorComponent& owner_, const String& name)
: owner (owner_), categoryName (name) : owner (owner_), categoryName (name)
{ {
} }
@@ -246,12 +318,12 @@ public:
{ {
if (getNumSubItems() == 0) 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) for (int i = 0; i < commands.size(); ++i)
{ {
if (owner.shouldCommandBeIncluded (commands[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; KeyMappingEditorComponent& owner;
String categoryName; 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) const bool showResetToDefaultButton)
: mappings (mappingManager), : mappings (mappingManager),
resetButton (TRANS ("reset to defaults")) resetButton (TRANS ("reset to defaults"))
{ {
jassert (mappingManager != 0); // can't be null!
mappingManager->addChangeListener (this);
setLinesDrawnForSubItems (false);
treeItem = new TopLevelItem (*this);
if (showResetToDefaultButton) if (showResetToDefaultButton)
{ {
addAndMakeVisible (&resetButton); addAndMakeVisible (&resetButton);
resetButton.addButtonListener (this);
resetButton.addButtonListener (treeItem);
} }
addAndMakeVisible (&tree); addAndMakeVisible (&tree);
tree.setColour (TreeView::backgroundColourId, findColour (backgroundColourId)); tree.setColour (TreeView::backgroundColourId, findColour (backgroundColourId));
tree.setRootItemVisible (false); tree.setRootItemVisible (false);
tree.setDefaultOpenness (true); tree.setDefaultOpenness (true);
tree.setRootItem (this);
tree.setRootItem (treeItem);
} }
KeyMappingEditorComponent::~KeyMappingEditorComponent() 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, void KeyMappingEditorComponent::setColours (const Colour& mainBackground,
const Colour& textColour) const Colour& textColour)
{ {
@@ -323,7 +442,7 @@ void KeyMappingEditorComponent::setColours (const Colour& mainBackground,
void KeyMappingEditorComponent::parentHierarchyChanged() void KeyMappingEditorComponent::parentHierarchyChanged()
{ {
changeListenerCallback (0);
treeItem->changeListenerCallback (0);
} }
void KeyMappingEditorComponent::resized() void KeyMappingEditorComponent::resized()
@@ -343,157 +462,19 @@ void KeyMappingEditorComponent::resized()
tree.setBounds (0, 0, getWidth(), h); 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) 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) 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) const String KeyMappingEditorComponent::getDescriptionForKeyPress (const KeyPress& key)


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

@@ -38,23 +38,18 @@
@see KeyPressMappingSet @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: public:
//============================================================================== //==============================================================================
/** Creates a KeyMappingEditorComponent. /** 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); bool showResetToDefaultButton);
/** Destructor. */ /** Destructor. */
@@ -69,9 +64,8 @@ public:
void setColours (const Colour& mainBackground, void setColours (const Colour& mainBackground,
const Colour& textColour); 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(); void parentHierarchyChanged();
/** @internal */ /** @internal */
void resized(); void resized();
/** @internal */
void changeListenerCallback (void*);
/** @internal */
bool mightContainSubItems();
/** @internal */
const String getUniqueName() const;
/** @internal */
void buttonClicked (Button* button);
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
private: private:
//============================================================================== //==============================================================================
friend class KeyMappingTreeViewItem;
friend class KeyCategoryTreeViewItem;
friend class KeyMappingItemComponent;
friend class KeyMappingChangeButton;
KeyPressMappingSet* mappings;
KeyPressMappingSet& mappings;
TreeView tree; TreeView tree;
TextButton resetButton; 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 (const KeyMappingEditorComponent&);
KeyMappingEditorComponent& operator= (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() 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) void Viewport::setViewedComponent (Component* const newViewedComponent)
{ {
if (contentComp.getComponent() != newViewedComponent) if (contentComp.getComponent() != newViewedComponent)
{ {
{
ScopedPointer<Component> oldCompDeleter (contentComp);
contentComp = 0;
}
deleteContentComp();
contentComp = newViewedComponent; contentComp = newViewedComponent;
if (contentComp != 0) 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) 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; ScrollBar horizontalScrollBar;
void updateVisibleArea(); void updateVisibleArea();
void deleteContentComp();
Viewport (const Viewport&); Viewport (const Viewport&);
Viewport& operator= (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: public:
//============================================================================== //==============================================================================
ItemComponent (const PopupMenu::Item& itemInfo_)
ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight)
: itemInfo (itemInfo_), : itemInfo (itemInfo_),
isHighlighted (false) isHighlighted (false)
{ {
if (itemInfo.customComp != 0) if (itemInfo.customComp != 0)
addAndMakeVisible (itemInfo.customComp); addAndMakeVisible (itemInfo.customComp);
int itemW = 80;
int itemH = 16;
getIdealSize (itemW, itemH, standardItemHeight);
setSize (itemW, jlimit (2, 600, itemH));
} }
~ItemComponent() ~ItemComponent()
@@ -258,35 +263,68 @@ class PopupMenu::Window : public Component,
{ {
public: 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"), : Component ("menu"),
owner (0),
owner (owner_),
activeSubMenu (0), activeSubMenu (0),
managerOfChosenCommand (0),
minimumWidth (0),
maximumNumColumns (7),
standardItemHeight (0),
managerOfChosenCommand (managerOfChosenCommand_),
componentAttachedTo (componentAttachedTo_),
componentAttachedToOriginal (componentAttachedTo_),
minimumWidth (minimumWidth_),
maximumNumColumns (maximumNumColumns_),
standardItemHeight (standardItemHeight_),
isOver (false), isOver (false),
hasBeenOver (false), hasBeenOver (false),
isDown (false), isDown (false),
needsToScroll (false), needsToScroll (false),
dismissOnMouseUp (dismissOnMouseUp_),
hideOnExit (false), hideOnExit (false),
disableMouseMoves (false), disableMouseMoves (false),
hasAnyJuceCompHadFocus (false), hasAnyJuceCompHadFocus (false),
numColumns (0), numColumns (0),
contentHeight (0), contentHeight (0),
childYOffset (0), childYOffset (0),
menuCreationTime (Time::getMillisecondCounter()),
timeEnteredCurrentChildComp (0), timeEnteredCurrentChildComp (0),
scrollAcceleration (1.0) scrollAcceleration (1.0)
{ {
menuCreationTime = lastFocused = lastScroll = Time::getMillisecondCounter();
setWantsKeyboardFocus (true);
lastFocused = lastScroll = menuCreationTime;
setWantsKeyboardFocus (false);
setMouseClickGrabsKeyboardFocus (false); setMouseClickGrabsKeyboardFocus (false);
setAlwaysOnTop (true); 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); getActiveWindows().add (this);
Desktop::getInstance().addGlobalMouseListener (this);
} }
~Window() ~Window()
@@ -294,69 +332,26 @@ public:
getActiveWindows().removeValue (this); getActiveWindows().removeValue (this);
Desktop::getInstance().removeGlobalMouseListener (this); Desktop::getInstance().removeGlobalMouseListener (this);
activeSubMenu = 0; activeSubMenu = 0;
deleteAllChildren();
items.clear();
} }
//============================================================================== //==============================================================================
static Window* create (const PopupMenu& menu, static Window* create (const PopupMenu& menu,
const bool dismissOnMouseUp,
bool dismissOnMouseUp,
Window* const owner_, Window* const owner_,
const Rectangle<int>& target, 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, ApplicationCommandManager** managerOfChosenCommand,
Component* const componentAttachedTo)
Component* componentAttachedTo)
{ {
if (menu.items.size() > 0) 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; return 0;
} }
@@ -394,19 +389,6 @@ public:
: childYOffset > 0); : 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 // hide this and all sub-comps
void hide (const PopupMenu::Item* const item, const bool makeInvisible) void hide (const PopupMenu::Item* const item, const bool makeInvisible)
@@ -610,8 +592,8 @@ public:
scrollAcceleration = jmin (4.0, scrollAcceleration * 1.04); scrollAcceleration = jmin (4.0, scrollAcceleration * 1.04);
int amount = 0; 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); alterChildYPos (localMousePos.getY() < PopupMenuSettings::scrollZone ? -amount : amount);
@@ -714,6 +696,7 @@ public:
private: private:
Window* owner; Window* owner;
OwnedArray <PopupMenu::ItemComponent> items;
Component::SafePointer<PopupMenu::ItemComponent> currentChild; Component::SafePointer<PopupMenu::ItemComponent> currentChild;
ScopedPointer <Window> activeSubMenu; ScopedPointer <Window> activeSubMenu;
ApplicationCommandManager** managerOfChosenCommand; ApplicationCommandManager** managerOfChosenCommand;
@@ -899,13 +882,13 @@ private:
{ {
int i, colW = 50, colH = 0; 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;) 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); colW = jmin (maxMenuW / jmax (1, numColumns - 2), colW + PopupMenuSettings::borderSize * 2);
@@ -932,9 +915,9 @@ private:
{ {
jassert (itemId != 0) 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 if (m != 0
&& m->itemInfo.itemId == itemId && m->itemInfo.itemId == itemId
@@ -1029,8 +1012,8 @@ private:
for (int col = 0; col < numColumns; ++col) 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]; const int colW = columnWidths [col];
@@ -1038,7 +1021,7 @@ private:
for (int i = 0; i < numChildren; ++i) 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()); c->setBounds (x, y, colW, c->getHeight());
y += c->getHeight(); y += c->getHeight();
} }
@@ -1187,14 +1170,14 @@ private:
disableTimerUntilMouseMoves(); disableTimerUntilMouseMoves();
PopupMenu::ItemComponent* mic = 0; PopupMenu::ItemComponent* mic = 0;
bool wasLastOne = (currentChild == 0); bool wasLastOne = (currentChild == 0);
const int numItems = getNumChildComponents();
const int numItems = items.size();
for (int i = 0; i < numItems + 1; ++i) for (int i = 0; i < numItems + 1; ++i)
{ {
int index = (delta > 0) ? i : (numItems - 1 - i); int index = (delta > 0) ? i : (numItems - 1 - i);
index = (index + numItems) % numItems; index = (index + numItems) % numItems;
mic = dynamic_cast <PopupMenu::ItemComponent*> (getChildComponent (index));
mic = items.getUnchecked (index);
if (mic != 0 && (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu()) if (mic != 0 && (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu())
&& wasLastOne) && wasLastOne)
@@ -1713,7 +1696,7 @@ bool PopupMenu::MenuItemIterator::next()
isSeparator = item->isSeparator; isSeparator = item->isSeparator;
isTicked = item->isTicked; isTicked = item->isTicked;
isEnabled = item->active; 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; isCustomComponent = (! isSectionHeader) && item->customComp != 0;
customColour = item->usesColour ? &(item->textColour) : 0; customColour = item->usesColour ? &(item->textColour) : 0;
customImage = item->image; customImage = item->image;


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

@@ -394,6 +394,7 @@ private:
friend class PopupMenuCustomComponent; friend class PopupMenuCustomComponent;
friend class MenuBarComponent; friend class MenuBarComponent;
friend class OwnedArray <Item>; friend class OwnedArray <Item>;
friend class OwnedArray <ItemComponent>;
friend class ScopedPointer <Window>; friend class ScopedPointer <Window>;
OwnedArray <Item> items; 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)); const Point<int> relativePos (comp->getLocalPoint (0, screenPos));
// (the contains() call is needed to test for overlapping desktop windows) // (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); 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" #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 class PropertySectionComponent : public Component
{ {
public: public:
PropertySectionComponent (const String& sectionTitle, PropertySectionComponent (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties, const Array <PropertyComponent*>& newProperties,
const bool open)
const bool sectionIsOpen_)
: Component (sectionTitle), : Component (sectionTitle),
titleHeight (sectionTitle.isNotEmpty() ? 22 : 0), 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() ~PropertySectionComponent()
{ {
deleteAllChildren();
propertyComps.clear();
} }
void paint (Graphics& g) void paint (Graphics& g)
@@ -90,16 +67,11 @@ public:
{ {
int y = titleHeight; 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()) 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; return y;
@@ -123,19 +90,13 @@ public:
void setOpen (const bool open) 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); PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0);
if (pp != 0) if (pp != 0)
@@ -145,22 +106,13 @@ public:
bool isOpen() const bool isOpen() const
{ {
return isOpen_;
return sectionIsOpen;
} }
void refreshAll() const 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) void mouseUp (const MouseEvent& e)
@@ -181,45 +133,65 @@ public:
} }
private: private:
OwnedArray <PropertyComponent> propertyComps;
int titleHeight; int titleHeight;
bool isOpen_;
bool sectionIsOpen;
PropertySectionComponent (const PropertySectionComponent&); PropertySectionComponent (const PropertySectionComponent&);
PropertySectionComponent& operator= (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() PropertyPanel::PropertyPanel()
@@ -239,7 +211,7 @@ PropertyPanel::~PropertyPanel()
//============================================================================== //==============================================================================
void PropertyPanel::paint (Graphics& g) void PropertyPanel::paint (Graphics& g)
{ {
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
{ {
g.setColour (Colours::black.withAlpha (0.5f)); g.setColour (Colours::black.withAlpha (0.5f));
g.setFont (14.0f); g.setFont (14.0f);
@@ -257,21 +229,19 @@ void PropertyPanel::resized()
//============================================================================== //==============================================================================
void PropertyPanel::clear() void PropertyPanel::clear()
{ {
if (propertyHolderComponent->getNumChildComponents() > 0)
if (propertyHolderComponent->getNumSections() > 0)
{ {
propertyHolderComponent->deleteAllChildren();
propertyHolderComponent->clear();
repaint(); repaint();
} }
} }
void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties) void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties)
{ {
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
repaint(); repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty,
newProperties,
true), 0);
propertyHolderComponent->addSection (new PropertySectionComponent (String::empty, newProperties, true));
updatePropHolderLayout(); updatePropHolderLayout();
} }
@@ -281,13 +251,10 @@ void PropertyPanel::addSection (const String& sectionTitle,
{ {
jassert (sectionTitle.isNotEmpty()); jassert (sectionTitle.isNotEmpty());
if (propertyHolderComponent->getNumChildComponents() == 0)
if (propertyHolderComponent->getNumSections() == 0)
repaint(); repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle,
newProperties,
shouldBeOpen), 0);
propertyHolderComponent->addSection (new PropertySectionComponent (sectionTitle, newProperties, shouldBeOpen));
updatePropHolderLayout(); updatePropHolderLayout();
} }
@@ -314,11 +281,11 @@ const StringArray PropertyPanel::getSectionNames() const
{ {
StringArray s; 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()); s.add (section->getName());
} }
@@ -329,11 +296,11 @@ bool PropertyPanel::isSectionOpen (const int sectionIndex) const
{ {
int index = 0; 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) if (index == sectionIndex)
return section->isOpen(); return section->isOpen();
@@ -349,11 +316,11 @@ void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeO
{ {
int index = 0; 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) if (index == sectionIndex)
{ {
@@ -370,11 +337,11 @@ void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool should
{ {
int index = 0; 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) if (index == sectionIndex)
{ {


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

@@ -66,6 +66,7 @@ public:
of (0, 0). of (0, 0).
*/ */
virtual void setOrigin (int x, int y) = 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 clipToRectangle (const Rectangle<int>& r) = 0;
virtual bool clipToRectangleList (const RectangleList& clipRegion) = 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) bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle<int>& r)
{ {
needToClip = true; needToClip = true;


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

@@ -49,6 +49,7 @@ public:
//============================================================================== //==============================================================================
bool isVectorDevice() const; bool isVectorDevice() const;
void setOrigin (int x, int y); void setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);
bool clipToRectangle (const Rectangle<int>& r); bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion); 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() 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); uint32 weight = (256 - subPixelX) * (256 - subPixelY);
c[0] += weight * src[0]; c[0] += weight * src[0];
c[1] += weight * src[1]; c[1] += weight * src[1];
c[2] += weight * src[2]; c[2] += weight * src[2];
c[3] += weight * src[3];
weight = subPixelX * (256 - subPixelY); 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; src += this->srcData.lineStride;
@@ -850,60 +848,56 @@ private:
c[0] += weight * src[0]; c[0] += weight * src[0];
c[1] += weight * src[1]; c[1] += weight * src[1];
c[2] += weight * src[2]; c[2] += weight * src[2];
c[3] += weight * src[3];
weight = subPixelX * subPixelY; 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[0] += weight * src[0];
c[1] += weight * src[1]; c[1] += weight * src[1];
c[2] += weight * src[2]; 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, 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[0] += weight * src[0];
c[1] += weight * src[1]; c[1] += weight * src[1];
c[2] += weight * src[2]; c[2] += weight * src[2];
src += this->srcData.lineStride; 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, 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: public:
SavedState (const Rectangle<int>& clip_, const int xOffset_, const int yOffset_) SavedState (const Rectangle<int>& clip_, const int xOffset_, const int yOffset_)
: clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), : 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_) SavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_)
: clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), : 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) 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) bool clipToRectangle (const Rectangle<int>& r)
{ {
if (clip != 0) 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; return clip != 0;
@@ -1837,11 +1860,17 @@ public:
{ {
if (clip != 0) 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; return clip != 0;
@@ -1851,8 +1880,17 @@ public:
{ {
if (clip != 0) 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; return clip != 0;
@@ -1863,7 +1901,7 @@ public:
if (clip != 0) if (clip != 0)
{ {
cloneClipIfMultiplyReferenced(); 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()) if (image.hasAlphaChannel())
{ {
cloneClipIfMultiplyReferenced(); cloneClipIfMultiplyReferenced();
clip = clip->clipToImageAlpha (image, t.translated ((float) xOffset, (float) yOffset),
clip = clip->clipToImageAlpha (image, getTransformWith (t),
interpolationQuality != Graphics::lowResamplingQuality); interpolationQuality != Graphics::lowResamplingQuality);
} }
else else
@@ -1888,12 +1926,28 @@ public:
bool clipRegionIntersects (const Rectangle<int>& r) const 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 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 (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 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 (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 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) void fillPath (Image& image, const Path& path, const AffineTransform& transform)
{ {
if (clip != 0) 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) void fillEdgeTable (Image& image, const EdgeTable& edgeTable, const float x, const int y)
{ {
jassert (isOnlyTranslated);
if (clip != 0) if (clip != 0)
{ {
SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable); SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable);
@@ -1970,7 +2044,7 @@ public:
ColourGradient g2 (*(fillType.gradient)); ColourGradient g2 (*(fillType.gradient));
g2.multiplyOpacity (fillType.getOpacity()); 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(); 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) 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 destData (destImage, true);
const Image::BitmapData srcData (sourceImage, false); const Image::BitmapData srcData (sourceImage, false);
@@ -2055,7 +2129,14 @@ public:
//============================================================================== //==============================================================================
SoftwareRendererClasses::ClipRegionBase::Ptr clip; SoftwareRendererClasses::ClipRegionBase::Ptr clip;
private:
AffineTransform complexTransform;
int xOffset, yOffset; int xOffset, yOffset;
public:
bool isOnlyTranslated;
Font font; Font font;
FillType fillType; FillType fillType;
Graphics::ResamplingQuality interpolationQuality; Graphics::ResamplingQuality interpolationQuality;
@@ -2067,6 +2148,22 @@ private:
clip = clip->clone(); 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&); SavedState& operator= (const SavedState&);
}; };
@@ -2100,6 +2197,11 @@ void LowLevelGraphicsSoftwareRenderer::setOrigin (int x, int y)
currentState->setOrigin (x, y); currentState->setOrigin (x, y);
} }
void LowLevelGraphicsSoftwareRenderer::addTransform (const AffineTransform& transform)
{
currentState->addTransform (transform);
}
bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle<int>& r) bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle<int>& r)
{ {
return currentState->clipToRectangle (r); return currentState->clipToRectangle (r);
@@ -2353,7 +2455,7 @@ void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineT
{ {
Font& f = currentState->font; Font& f = currentState->font;
if (transform.isOnlyTranslation())
if (transform.isOnlyTranslation() && currentState->isOnlyTranslated)
{ {
GlyphCache::getInstance()->drawGlyph (*currentState, image, f, glyphNumber, GlyphCache::getInstance()->drawGlyph (*currentState, image, f, glyphNumber,
transform.getTranslationX(), 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 setOrigin (int x, int y);
void addTransform (const AffineTransform& transform);
bool clipToRectangle (const Rectangle<int>& r); bool clipToRectangle (const Rectangle<int>& r);
bool clipToRectangleList (const RectangleList& clipRegion); 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 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; 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); 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) if (trueIfInAChildWindow)
@@ -988,7 +976,7 @@ public:
return false; 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 false;
return child == None; return child == None;


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

@@ -180,6 +180,16 @@ public:
lastClipRect.translate (-x, -y); 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) bool clipToRectangle (const Rectangle<int>& r)
{ {
CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); 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); currentState->origin.addXY (x, y);
} }
void addTransform (const AffineTransform& transform)
{
//xxx todo
jassertfalse;
}
bool clipToRectangle (const Rectangle<int>& r) bool clipToRectangle (const Rectangle<int>& r)
{ {
currentState->clipToRectangle (r); currentState->clipToRectangle (r);


Loading…
Cancel
Save