2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
30 #include "juce_TableHeaderComponent.h"
31 #include "../../graphics/imaging/juce_Image.h"
32 #include "../../../text/juce_XmlDocument.h"
33 #include "../lookandfeel/juce_LookAndFeel.h"
34 #include "../layout/juce_StretchableObjectResizer.h"
37 //==============================================================================
38 class DragOverlayComp
: public Component
41 DragOverlayComp (const Image
& image_
)
44 image
.duplicateIfShared();
45 image
.multiplyAllAlphas (0.8f
);
46 setAlwaysOnTop (true);
49 void paint (Graphics
& g
)
51 g
.drawImageAt (image
, 0, 0);
57 JUCE_DECLARE_NON_COPYABLE (DragOverlayComp
);
61 //==============================================================================
62 TableHeaderComponent::TableHeaderComponent()
63 : columnsChanged (false),
64 columnsResized (false),
68 columnIdBeingResized (0),
69 columnIdBeingDragged (0),
70 columnIdUnderMouse (0),
71 lastDeliberateWidth (0)
75 TableHeaderComponent::~TableHeaderComponent()
77 dragOverlayComp
= nullptr;
80 //==============================================================================
81 void TableHeaderComponent::setPopupMenuActive (const bool hasMenu
)
86 bool TableHeaderComponent::isPopupMenuActive() const { return menuActive
; }
89 //==============================================================================
90 int TableHeaderComponent::getNumColumns (const bool onlyCountVisibleColumns
) const
92 if (onlyCountVisibleColumns
)
96 for (int i
= columns
.size(); --i
>= 0;)
97 if (columns
.getUnchecked(i
)->isVisible())
104 return columns
.size();
108 String
TableHeaderComponent::getColumnName (const int columnId
) const
110 const ColumnInfo
* const ci
= getInfoForId (columnId
);
111 return ci
!= nullptr ? ci
->name
: String::empty
;
114 void TableHeaderComponent::setColumnName (const int columnId
, const String
& newName
)
116 ColumnInfo
* const ci
= getInfoForId (columnId
);
118 if (ci
!= nullptr && ci
->name
!= newName
)
121 sendColumnsChanged();
125 void TableHeaderComponent::addColumn (const String
& columnName
,
128 const int minimumWidth
,
129 const int maximumWidth
,
130 const int propertyFlags
,
131 const int insertIndex
)
133 // can't have a duplicate or null ID!
134 jassert (columnId
!= 0 && getIndexOfColumnId (columnId
, false) < 0);
137 ColumnInfo
* const ci
= new ColumnInfo();
138 ci
->name
= columnName
;
141 ci
->lastDeliberateWidth
= width
;
142 ci
->minimumWidth
= minimumWidth
;
143 ci
->maximumWidth
= maximumWidth
;
144 if (ci
->maximumWidth
< 0)
145 ci
->maximumWidth
= std::numeric_limits
<int>::max();
146 jassert (ci
->maximumWidth
>= ci
->minimumWidth
);
147 ci
->propertyFlags
= propertyFlags
;
149 columns
.insert (insertIndex
, ci
);
150 sendColumnsChanged();
153 void TableHeaderComponent::removeColumn (const int columnIdToRemove
)
155 const int index
= getIndexOfColumnId (columnIdToRemove
, false);
159 columns
.remove (index
);
161 sendColumnsChanged();
165 void TableHeaderComponent::removeAllColumns()
167 if (columns
.size() > 0)
170 sendColumnsChanged();
174 void TableHeaderComponent::moveColumn (const int columnId
, int newIndex
)
176 const int currentIndex
= getIndexOfColumnId (columnId
, false);
177 newIndex
= visibleIndexToTotalIndex (newIndex
);
179 if (columns
[currentIndex
] != 0 && currentIndex
!= newIndex
)
181 columns
.move (currentIndex
, newIndex
);
182 sendColumnsChanged();
186 int TableHeaderComponent::getColumnWidth (const int columnId
) const
188 const ColumnInfo
* const ci
= getInfoForId (columnId
);
189 return ci
!= nullptr ? ci
->width
: 0;
192 void TableHeaderComponent::setColumnWidth (const int columnId
, const int newWidth
)
194 ColumnInfo
* const ci
= getInfoForId (columnId
);
196 if (ci
!= nullptr && ci
->width
!= newWidth
)
198 const int numColumns
= getNumColumns (true);
200 ci
->lastDeliberateWidth
= ci
->width
201 = jlimit (ci
->minimumWidth
, ci
->maximumWidth
, newWidth
);
205 const int index
= getIndexOfColumnId (columnId
, true) + 1;
207 if (isPositiveAndBelow (index
, numColumns
))
209 const int x
= getColumnPosition (index
).getX();
211 if (lastDeliberateWidth
== 0)
212 lastDeliberateWidth
= getTotalWidth();
214 resizeColumnsToFit (visibleIndexToTotalIndex (index
), lastDeliberateWidth
- x
);
219 columnsResized
= true;
220 triggerAsyncUpdate();
224 //==============================================================================
225 int TableHeaderComponent::getIndexOfColumnId (const int columnId
, const bool onlyCountVisibleColumns
) const
229 for (int i
= 0; i
< columns
.size(); ++i
)
231 if ((! onlyCountVisibleColumns
) || columns
.getUnchecked(i
)->isVisible())
233 if (columns
.getUnchecked(i
)->id
== columnId
)
243 int TableHeaderComponent::getColumnIdOfIndex (int index
, const bool onlyCountVisibleColumns
) const
245 if (onlyCountVisibleColumns
)
246 index
= visibleIndexToTotalIndex (index
);
248 const ColumnInfo
* const ci
= columns
[index
];
249 return (ci
!= nullptr) ? ci
->id
: 0;
252 const Rectangle
<int> TableHeaderComponent::getColumnPosition (const int index
) const
254 int x
= 0, width
= 0, n
= 0;
256 for (int i
= 0; i
< columns
.size(); ++i
)
260 if (columns
.getUnchecked(i
)->isVisible())
262 width
= columns
.getUnchecked(i
)->width
;
273 return Rectangle
<int> (x
, 0, width
, getHeight());
276 int TableHeaderComponent::getColumnIdAtX (const int xToFind
) const
282 for (int i
= 0; i
< columns
.size(); ++i
)
284 const ColumnInfo
* const ci
= columns
.getUnchecked(i
);
299 int TableHeaderComponent::getTotalWidth() const
303 for (int i
= columns
.size(); --i
>= 0;)
304 if (columns
.getUnchecked(i
)->isVisible())
305 w
+= columns
.getUnchecked(i
)->width
;
310 void TableHeaderComponent::setStretchToFitActive (const bool shouldStretchToFit
)
312 stretchToFit
= shouldStretchToFit
;
313 lastDeliberateWidth
= getTotalWidth();
317 bool TableHeaderComponent::isStretchToFitActive() const
322 void TableHeaderComponent::resizeAllColumnsToFit (int targetTotalWidth
)
324 if (stretchToFit
&& getWidth() > 0
325 && columnIdBeingResized
== 0 && columnIdBeingDragged
== 0)
327 lastDeliberateWidth
= targetTotalWidth
;
328 resizeColumnsToFit (0, targetTotalWidth
);
332 void TableHeaderComponent::resizeColumnsToFit (int firstColumnIndex
, int targetTotalWidth
)
334 targetTotalWidth
= jmax (targetTotalWidth
, 0);
336 StretchableObjectResizer sor
;
338 for (i
= firstColumnIndex
; i
< columns
.size(); ++i
)
340 ColumnInfo
* const ci
= columns
.getUnchecked(i
);
343 sor
.addItem (ci
->lastDeliberateWidth
, ci
->minimumWidth
, ci
->maximumWidth
);
346 sor
.resizeToFit (targetTotalWidth
);
349 for (i
= firstColumnIndex
; i
< columns
.size(); ++i
)
351 ColumnInfo
* const ci
= columns
.getUnchecked(i
);
355 const int newWidth
= jlimit (ci
->minimumWidth
, ci
->maximumWidth
,
356 (int) std::floor (sor
.getItemSize (visIndex
++)));
358 if (newWidth
!= ci
->width
)
360 ci
->width
= newWidth
;
362 columnsResized
= true;
363 triggerAsyncUpdate();
369 void TableHeaderComponent::setColumnVisible (const int columnId
, const bool shouldBeVisible
)
371 ColumnInfo
* const ci
= getInfoForId (columnId
);
373 if (ci
!= nullptr && shouldBeVisible
!= ci
->isVisible())
376 ci
->propertyFlags
|= visible
;
378 ci
->propertyFlags
&= ~visible
;
380 sendColumnsChanged();
385 bool TableHeaderComponent::isColumnVisible (const int columnId
) const
387 const ColumnInfo
* const ci
= getInfoForId (columnId
);
388 return ci
!= nullptr && ci
->isVisible();
391 //==============================================================================
392 void TableHeaderComponent::setSortColumnId (const int columnId
, const bool sortForwards
)
394 if (getSortColumnId() != columnId
|| isSortedForwards() != sortForwards
)
396 for (int i
= columns
.size(); --i
>= 0;)
397 columns
.getUnchecked(i
)->propertyFlags
&= ~(sortedForwards
| sortedBackwards
);
399 ColumnInfo
* const ci
= getInfoForId (columnId
);
402 ci
->propertyFlags
|= (sortForwards
? sortedForwards
: sortedBackwards
);
408 int TableHeaderComponent::getSortColumnId() const
410 for (int i
= columns
.size(); --i
>= 0;)
411 if ((columns
.getUnchecked(i
)->propertyFlags
& (sortedForwards
| sortedBackwards
)) != 0)
412 return columns
.getUnchecked(i
)->id
;
417 bool TableHeaderComponent::isSortedForwards() const
419 for (int i
= columns
.size(); --i
>= 0;)
420 if ((columns
.getUnchecked(i
)->propertyFlags
& (sortedForwards
| sortedBackwards
)) != 0)
421 return (columns
.getUnchecked(i
)->propertyFlags
& sortedForwards
) != 0;
426 void TableHeaderComponent::reSortTable()
430 triggerAsyncUpdate();
433 //==============================================================================
434 String
TableHeaderComponent::toString() const
438 XmlElement
doc ("TABLELAYOUT");
440 doc
.setAttribute ("sortedCol", getSortColumnId());
441 doc
.setAttribute ("sortForwards", isSortedForwards());
443 for (int i
= 0; i
< columns
.size(); ++i
)
445 const ColumnInfo
* const ci
= columns
.getUnchecked (i
);
447 XmlElement
* const e
= doc
.createNewChildElement ("COLUMN");
448 e
->setAttribute ("id", ci
->id
);
449 e
->setAttribute ("visible", ci
->isVisible());
450 e
->setAttribute ("width", ci
->width
);
453 return doc
.createDocument (String::empty
, true, false);
456 void TableHeaderComponent::restoreFromString (const String
& storedVersion
)
458 ScopedPointer
<XmlElement
> storedXml (XmlDocument::parse (storedVersion
));
461 if (storedXml
!= nullptr && storedXml
->hasTagName ("TABLELAYOUT"))
463 forEachXmlChildElement (*storedXml
, col
)
465 const int tabId
= col
->getIntAttribute ("id");
467 ColumnInfo
* const ci
= getInfoForId (tabId
);
471 columns
.move (columns
.indexOf (ci
), index
);
472 ci
->width
= col
->getIntAttribute ("width");
473 setColumnVisible (tabId
, col
->getBoolAttribute ("visible"));
479 columnsResized
= true;
480 sendColumnsChanged();
482 setSortColumnId (storedXml
->getIntAttribute ("sortedCol"),
483 storedXml
->getBoolAttribute ("sortForwards", true));
487 //==============================================================================
488 void TableHeaderComponent::addListener (Listener
* const newListener
)
490 listeners
.addIfNotAlreadyThere (newListener
);
493 void TableHeaderComponent::removeListener (Listener
* const listenerToRemove
)
495 listeners
.removeValue (listenerToRemove
);
498 //==============================================================================
499 void TableHeaderComponent::columnClicked (int columnId
, const ModifierKeys
& mods
)
501 const ColumnInfo
* const ci
= getInfoForId (columnId
);
503 if (ci
!= nullptr && (ci
->propertyFlags
& sortable
) != 0 && ! mods
.isPopupMenu())
504 setSortColumnId (columnId
, (ci
->propertyFlags
& sortedForwards
) == 0);
507 void TableHeaderComponent::addMenuItems (PopupMenu
& menu
, const int /*columnIdClicked*/)
509 for (int i
= 0; i
< columns
.size(); ++i
)
511 const ColumnInfo
* const ci
= columns
.getUnchecked(i
);
513 if ((ci
->propertyFlags
& appearsOnColumnMenu
) != 0)
514 menu
.addItem (ci
->id
, ci
->name
,
515 (ci
->propertyFlags
& (sortedForwards
| sortedBackwards
)) == 0,
516 isColumnVisible (ci
->id
));
520 void TableHeaderComponent::reactToMenuItem (const int menuReturnId
, const int /*columnIdClicked*/)
522 if (getIndexOfColumnId (menuReturnId
, false) >= 0)
523 setColumnVisible (menuReturnId
, ! isColumnVisible (menuReturnId
));
526 void TableHeaderComponent::paint (Graphics
& g
)
528 LookAndFeel
& lf
= getLookAndFeel();
530 lf
.drawTableHeaderBackground (g
, *this);
532 const Rectangle
<int> clip (g
.getClipBounds());
535 for (int i
= 0; i
< columns
.size(); ++i
)
537 const ColumnInfo
* const ci
= columns
.getUnchecked(i
);
541 if (x
+ ci
->width
> clip
.getX()
542 && (ci
->id
!= columnIdBeingDragged
543 || dragOverlayComp
== nullptr
544 || ! dragOverlayComp
->isVisible()))
546 Graphics::ScopedSaveState
ss (g
);
549 g
.reduceClipRegion (0, 0, ci
->width
, getHeight());
551 lf
.drawTableHeaderColumn (g
, ci
->name
, ci
->id
, ci
->width
, getHeight(),
552 ci
->id
== columnIdUnderMouse
,
553 ci
->id
== columnIdUnderMouse
&& isMouseButtonDown(),
559 if (x
>= clip
.getRight())
565 void TableHeaderComponent::resized()
569 void TableHeaderComponent::mouseMove (const MouseEvent
& e
)
571 updateColumnUnderMouse (e
.x
, e
.y
);
574 void TableHeaderComponent::mouseEnter (const MouseEvent
& e
)
576 updateColumnUnderMouse (e
.x
, e
.y
);
579 void TableHeaderComponent::mouseExit (const MouseEvent
& e
)
581 updateColumnUnderMouse (e
.x
, e
.y
);
584 void TableHeaderComponent::mouseDown (const MouseEvent
& e
)
587 columnIdBeingResized
= 0;
588 columnIdBeingDragged
= 0;
590 if (columnIdUnderMouse
!= 0)
592 draggingColumnOffset
= e
.x
- getColumnPosition (getIndexOfColumnId (columnIdUnderMouse
, true)).getX();
594 if (e
.mods
.isPopupMenu())
595 columnClicked (columnIdUnderMouse
, e
.mods
);
598 if (menuActive
&& e
.mods
.isPopupMenu())
599 showColumnChooserMenu (columnIdUnderMouse
);
602 void TableHeaderComponent::mouseDrag (const MouseEvent
& e
)
604 if (columnIdBeingResized
== 0
605 && columnIdBeingDragged
== 0
606 && ! (e
.mouseWasClicked() || e
.mods
.isPopupMenu()))
608 dragOverlayComp
= nullptr;
610 columnIdBeingResized
= getResizeDraggerAt (e
.getMouseDownX());
612 if (columnIdBeingResized
!= 0)
614 const ColumnInfo
* const ci
= getInfoForId (columnIdBeingResized
);
615 initialColumnWidth
= ci
->width
;
623 if (columnIdBeingResized
!= 0)
625 const ColumnInfo
* const ci
= getInfoForId (columnIdBeingResized
);
629 int w
= jlimit (ci
->minimumWidth
, ci
->maximumWidth
,
630 initialColumnWidth
+ e
.getDistanceFromDragStartX());
634 // prevent us dragging a column too far right if we're in stretch-to-fit mode
635 int minWidthOnRight
= 0;
636 for (int i
= getIndexOfColumnId (columnIdBeingResized
, false) + 1; i
< columns
.size(); ++i
)
637 if (columns
.getUnchecked (i
)->isVisible())
638 minWidthOnRight
+= columns
.getUnchecked (i
)->minimumWidth
;
640 const Rectangle
<int> currentPos (getColumnPosition (getIndexOfColumnId (columnIdBeingResized
, true)));
641 w
= jmax (ci
->minimumWidth
, jmin (w
, getWidth() - minWidthOnRight
- currentPos
.getX()));
644 setColumnWidth (columnIdBeingResized
, w
);
647 else if (columnIdBeingDragged
!= 0)
649 if (e
.y
>= -50 && e
.y
< getHeight() + 50)
651 if (dragOverlayComp
!= nullptr)
653 dragOverlayComp
->setVisible (true);
654 dragOverlayComp
->setBounds (jlimit (0,
655 jmax (0, getTotalWidth() - dragOverlayComp
->getWidth()),
656 e
.x
- draggingColumnOffset
),
658 dragOverlayComp
->getWidth(),
661 for (int i
= columns
.size(); --i
>= 0;)
663 const int currentIndex
= getIndexOfColumnId (columnIdBeingDragged
, true);
664 int newIndex
= currentIndex
;
668 // if the previous column isn't draggable, we can't move our column
669 // past it, because that'd change the undraggable column's position..
670 const ColumnInfo
* const previous
= columns
.getUnchecked (newIndex
- 1);
672 if ((previous
->propertyFlags
& draggable
) != 0)
674 const int leftOfPrevious
= getColumnPosition (newIndex
- 1).getX();
675 const int rightOfCurrent
= getColumnPosition (newIndex
).getRight();
677 if (abs (dragOverlayComp
->getX() - leftOfPrevious
)
678 < abs (dragOverlayComp
->getRight() - rightOfCurrent
))
685 if (newIndex
< columns
.size() - 1)
687 // if the next column isn't draggable, we can't move our column
688 // past it, because that'd change the undraggable column's position..
689 const ColumnInfo
* const nextCol
= columns
.getUnchecked (newIndex
+ 1);
691 if ((nextCol
->propertyFlags
& draggable
) != 0)
693 const int leftOfCurrent
= getColumnPosition (newIndex
).getX();
694 const int rightOfNext
= getColumnPosition (newIndex
+ 1).getRight();
696 if (abs (dragOverlayComp
->getX() - leftOfCurrent
)
697 > abs (dragOverlayComp
->getRight() - rightOfNext
))
704 if (newIndex
!= currentIndex
)
705 moveColumn (columnIdBeingDragged
, newIndex
);
713 endDrag (draggingColumnOriginalIndex
);
718 void TableHeaderComponent::beginDrag (const MouseEvent
& e
)
720 if (columnIdBeingDragged
== 0)
722 columnIdBeingDragged
= getColumnIdAtX (e
.getMouseDownX());
724 const ColumnInfo
* const ci
= getInfoForId (columnIdBeingDragged
);
726 if (ci
== nullptr || (ci
->propertyFlags
& draggable
) == 0)
728 columnIdBeingDragged
= 0;
732 draggingColumnOriginalIndex
= getIndexOfColumnId (columnIdBeingDragged
, true);
734 const Rectangle
<int> columnRect (getColumnPosition (draggingColumnOriginalIndex
));
736 const int temp
= columnIdBeingDragged
;
737 columnIdBeingDragged
= 0;
739 addAndMakeVisible (dragOverlayComp
= new DragOverlayComp (createComponentSnapshot (columnRect
, false)));
740 columnIdBeingDragged
= temp
;
742 dragOverlayComp
->setBounds (columnRect
);
744 for (int i
= listeners
.size(); --i
>= 0;)
746 listeners
.getUnchecked(i
)->tableColumnDraggingChanged (this, columnIdBeingDragged
);
747 i
= jmin (i
, listeners
.size() - 1);
753 void TableHeaderComponent::endDrag (const int finalIndex
)
755 if (columnIdBeingDragged
!= 0)
757 moveColumn (columnIdBeingDragged
, finalIndex
);
759 columnIdBeingDragged
= 0;
762 for (int i
= listeners
.size(); --i
>= 0;)
764 listeners
.getUnchecked(i
)->tableColumnDraggingChanged (this, 0);
765 i
= jmin (i
, listeners
.size() - 1);
770 void TableHeaderComponent::mouseUp (const MouseEvent
& e
)
774 for (int i
= columns
.size(); --i
>= 0;)
775 if (columns
.getUnchecked (i
)->isVisible())
776 columns
.getUnchecked (i
)->lastDeliberateWidth
= columns
.getUnchecked (i
)->width
;
778 columnIdBeingResized
= 0;
781 endDrag (getIndexOfColumnId (columnIdBeingDragged
, true));
783 updateColumnUnderMouse (e
.x
, e
.y
);
785 if (columnIdUnderMouse
!= 0 && e
.mouseWasClicked() && ! e
.mods
.isPopupMenu())
786 columnClicked (columnIdUnderMouse
, e
.mods
);
788 dragOverlayComp
= nullptr;
791 const MouseCursor
TableHeaderComponent::getMouseCursor()
793 if (columnIdBeingResized
!= 0 || (getResizeDraggerAt (getMouseXYRelative().getX()) != 0 && ! isMouseButtonDown()))
794 return MouseCursor (MouseCursor::LeftRightResizeCursor
);
796 return Component::getMouseCursor();
799 //==============================================================================
800 bool TableHeaderComponent::ColumnInfo::isVisible() const
802 return (propertyFlags
& TableHeaderComponent::visible
) != 0;
805 TableHeaderComponent::ColumnInfo
* TableHeaderComponent::getInfoForId (const int id
) const
807 for (int i
= columns
.size(); --i
>= 0;)
808 if (columns
.getUnchecked(i
)->id
== id
)
809 return columns
.getUnchecked(i
);
814 int TableHeaderComponent::visibleIndexToTotalIndex (const int visibleIndex
) const
818 for (int i
= 0; i
< columns
.size(); ++i
)
820 if (columns
.getUnchecked(i
)->isVisible())
822 if (n
== visibleIndex
)
832 void TableHeaderComponent::sendColumnsChanged()
834 if (stretchToFit
&& lastDeliberateWidth
> 0)
835 resizeAllColumnsToFit (lastDeliberateWidth
);
838 columnsChanged
= true;
839 triggerAsyncUpdate();
842 void TableHeaderComponent::handleAsyncUpdate()
844 const bool changed
= columnsChanged
|| sortChanged
;
845 const bool sized
= columnsResized
|| changed
;
846 const bool sorted
= sortChanged
;
847 columnsChanged
= false;
848 columnsResized
= false;
853 for (int i
= listeners
.size(); --i
>= 0;)
855 listeners
.getUnchecked(i
)->tableSortOrderChanged (this);
856 i
= jmin (i
, listeners
.size() - 1);
862 for (int i
= listeners
.size(); --i
>= 0;)
864 listeners
.getUnchecked(i
)->tableColumnsChanged (this);
865 i
= jmin (i
, listeners
.size() - 1);
871 for (int i
= listeners
.size(); --i
>= 0;)
873 listeners
.getUnchecked(i
)->tableColumnsResized (this);
874 i
= jmin (i
, listeners
.size() - 1);
879 int TableHeaderComponent::getResizeDraggerAt (const int mouseX
) const
881 if (isPositiveAndBelow (mouseX
, getWidth()))
883 const int draggableDistance
= 3;
886 for (int i
= 0; i
< columns
.size(); ++i
)
888 const ColumnInfo
* const ci
= columns
.getUnchecked(i
);
892 if (abs (mouseX
- (x
+ ci
->width
)) <= draggableDistance
893 && (ci
->propertyFlags
& resizable
) != 0)
904 void TableHeaderComponent::updateColumnUnderMouse (int x
, int y
)
906 const int newCol
= (reallyContains (Point
<int> (x
, y
), true) && getResizeDraggerAt (x
) == 0)
907 ? getColumnIdAtX (x
) : 0;
909 if (newCol
!= columnIdUnderMouse
)
911 columnIdUnderMouse
= newCol
;
916 static void tableHeaderMenuCallback (int result
, TableHeaderComponent
* tableHeader
, int columnIdClicked
)
918 if (tableHeader
!= nullptr && result
!= 0)
919 tableHeader
->reactToMenuItem (result
, columnIdClicked
);
922 void TableHeaderComponent::showColumnChooserMenu (const int columnIdClicked
)
925 addMenuItems (m
, columnIdClicked
);
927 if (m
.getNumItems() > 0)
929 m
.setLookAndFeel (&getLookAndFeel());
931 m
.showMenuAsync (PopupMenu::Options(),
932 ModalCallbackFunction::forComponent (tableHeaderMenuCallback
, this, columnIdClicked
));
936 void TableHeaderComponent::Listener::tableColumnDraggingChanged (TableHeaderComponent
*, int)