|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2020 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 6 End-User License
- Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
-
- End User License Agreement: www.juce.com/juce-6-licence
- Privacy Policy: www.juce.com/juce-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- //==============================================================================
- /**
- A component that displays a strip of column headings for a table, and allows these
- to be resized, dragged around, etc.
-
- This is just the component that goes at the top of a table. You can use it
- directly for custom components, or to create a simple table, use the
- TableListBox class.
-
- To use one of these, create it and use addColumn() to add all the columns that you need.
- Each column must be given a unique ID number that's used to refer to it.
-
- @see TableListBox, TableHeaderComponent::Listener
-
- @tags{GUI}
- */
- class JUCE_API TableHeaderComponent : public Component,
- private AsyncUpdater
- {
- public:
- //==============================================================================
- /** Creates an empty table header.
- */
- TableHeaderComponent();
-
- /** Destructor. */
- ~TableHeaderComponent() override;
-
- //==============================================================================
- /** A combination of these flags are passed into the addColumn() method to specify
- the properties of a column.
- */
- enum ColumnPropertyFlags
- {
- visible = 1, /**< If this is set, the column will be shown; if not, it will be hidden until the user enables it with the pop-up menu. */
- resizable = 2, /**< If this is set, the column can be resized by dragging it. */
- draggable = 4, /**< If this is set, the column can be dragged around to change its order in the table. */
- appearsOnColumnMenu = 8, /**< If this is set, the column will be shown on the pop-up menu allowing it to be hidden/shown. */
- sortable = 16, /**< If this is set, then clicking on the column header will set it to be the sort column, and clicking again will reverse the order. */
- sortedForwards = 32, /**< If this is set, the column is currently the one by which the table is sorted (forwards). */
- sortedBackwards = 64, /**< If this is set, the column is currently the one by which the table is sorted (backwards). */
-
- /** This set of default flags is used as the default parameter value in addColumn(). */
- defaultFlags = (visible | resizable | draggable | appearsOnColumnMenu | sortable),
-
- /** A quick way of combining flags for a column that's not resizable. */
- notResizable = (visible | draggable | appearsOnColumnMenu | sortable),
-
- /** A quick way of combining flags for a column that's not resizable or sortable. */
- notResizableOrSortable = (visible | draggable | appearsOnColumnMenu),
-
- /** A quick way of combining flags for a column that's not sortable. */
- notSortable = (visible | resizable | draggable | appearsOnColumnMenu)
- };
-
- /** Adds a column to the table.
-
- This will add a column, and asynchronously call the tableColumnsChanged() method of any
- registered listeners.
-
- @param columnName the name of the new column. It's ok to have two or more columns with the same name
- @param columnId an ID for this column. The ID can be any number apart from 0, but every column must have
- a unique ID. This is used to identify the column later on, after the user may have
- changed the order that they appear in
- @param width the initial width of the column, in pixels
- @param maximumWidth a maximum width that the column can take when the user is resizing it. This only applies
- if the 'resizable' flag is specified for this column
- @param minimumWidth a minimum width that the column can take when the user is resizing it. This only applies
- if the 'resizable' flag is specified for this column
- @param propertyFlags a combination of some of the values from the ColumnPropertyFlags enum, to define the
- properties of this column
- @param insertIndex the index at which the column should be added. A value of 0 puts it at the start (left-hand side)
- and -1 puts it at the end (right-hand size) of the table. Note that the index the index within
- all columns, not just the index amongst those that are currently visible
- */
- void addColumn (const String& columnName,
- int columnId,
- int width,
- int minimumWidth = 30,
- int maximumWidth = -1,
- int propertyFlags = defaultFlags,
- int insertIndex = -1);
-
- /** Removes a column with the given ID.
-
- If there is such a column, this will asynchronously call the tableColumnsChanged() method of any
- registered listeners.
- */
- void removeColumn (int columnIdToRemove);
-
- /** Deletes all columns from the table.
-
- If there are any columns to remove, this will asynchronously call the tableColumnsChanged() method of any
- registered listeners.
- */
- void removeAllColumns();
-
- /** Returns the number of columns in the table.
-
- If onlyCountVisibleColumns is true, this will return the number of visible columns; otherwise it'll
- return the total number of columns, including hidden ones.
-
- @see isColumnVisible
- */
- int getNumColumns (bool onlyCountVisibleColumns) const;
-
- /** Returns the name for a column.
- @see setColumnName
- */
- String getColumnName (int columnId) const;
-
- /** Changes the name of a column. */
- void setColumnName (int columnId, const String& newName);
-
- /** Moves a column to a different index in the table.
-
- @param columnId the column to move
- @param newVisibleIndex the target index for it, from 0 to the number of columns currently visible.
- */
- void moveColumn (int columnId, int newVisibleIndex);
-
- /** Returns the width of one of the columns.
- */
- int getColumnWidth (int columnId) const;
-
- /** Changes the width of a column.
-
- This will cause an asynchronous callback to the tableColumnsResized() method of any registered listeners.
- */
- void setColumnWidth (int columnId, int newWidth);
-
- /** Shows or hides a column.
-
- This can cause an asynchronous callback to the tableColumnsChanged() method of any registered listeners.
- @see isColumnVisible
- */
- void setColumnVisible (int columnId, bool shouldBeVisible);
-
- /** Returns true if this column is currently visible.
- @see setColumnVisible
- */
- bool isColumnVisible (int columnId) const;
-
- /** Changes the column which is the sort column.
-
- This can cause an asynchronous callback to the tableSortOrderChanged() method of any registered listeners.
-
- If this method doesn't actually change the column ID, then no re-sort will take place (you can
- call reSortTable() to force a re-sort to happen if you've modified the table's contents).
-
- @see getSortColumnId, isSortedForwards, reSortTable
- */
- void setSortColumnId (int columnId, bool sortForwards);
-
- /** Returns the column ID by which the table is currently sorted, or 0 if it is unsorted.
-
- @see setSortColumnId, isSortedForwards
- */
- int getSortColumnId() const;
-
- /** Returns true if the table is currently sorted forwards, or false if it's backwards.
- @see setSortColumnId
- */
- bool isSortedForwards() const;
-
- /** Triggers a re-sort of the table according to the current sort-column.
-
- If you modify the table's contents, you can call this to signal that the table needs
- to be re-sorted.
-
- (This doesn't do any sorting synchronously - it just asynchronously sends a call to the
- tableSortOrderChanged() method of any listeners).
- */
- void reSortTable();
-
- //==============================================================================
- /** Returns the total width of all the visible columns in the table.
- */
- int getTotalWidth() const;
-
- /** Returns the index of a given column.
-
- If there's no such column ID, this will return -1.
-
- If onlyCountVisibleColumns is true, this will return the index amongst the visible columns;
- otherwise it'll return the index amongst all the columns, including any hidden ones.
- */
- int getIndexOfColumnId (int columnId, bool onlyCountVisibleColumns) const;
-
- /** Returns the ID of the column at a given index.
-
- If onlyCountVisibleColumns is true, this will count the index amongst the visible columns;
- otherwise it'll count it amongst all the columns, including any hidden ones.
-
- If the index is out-of-range, it'll return 0.
- */
- int getColumnIdOfIndex (int index, bool onlyCountVisibleColumns) const;
-
- /** Returns the rectangle containing of one of the columns.
-
- The index is an index from 0 to the number of columns that are currently visible (hidden
- ones are not counted). It returns a rectangle showing the position of the column relative
- to this component's top-left. If the index is out-of-range, an empty rectangle is returned.
- */
- Rectangle<int> getColumnPosition (int index) const;
-
- /** Finds the column ID at a given x-position in the component.
- If there is a column at this point this returns its ID, or if not, it will return 0.
- */
- int getColumnIdAtX (int xToFind) const;
-
- /** If set to true, this indicates that the columns should be expanded or shrunk to fill the
- entire width of the component.
-
- By default this is disabled. Turning it on also means that when resizing a column, those
- on the right will be squashed to fit.
- */
- void setStretchToFitActive (bool shouldStretchToFit);
-
- /** Returns true if stretch-to-fit has been enabled.
- @see setStretchToFitActive
- */
- bool isStretchToFitActive() const;
-
- /** If stretch-to-fit is enabled, this will resize all the columns to make them fit into the
- specified width, keeping their relative proportions the same.
-
- If the minimum widths of the columns are too wide to fit into this space, it may
- actually end up wider.
- */
- void resizeAllColumnsToFit (int targetTotalWidth);
-
- //==============================================================================
- /** Enables or disables the pop-up menu.
-
- The default menu allows the user to show or hide columns. You can add custom
- items to this menu by overloading the addMenuItems() and reactToMenuItem() methods.
-
- By default the menu is enabled.
-
- @see isPopupMenuActive, addMenuItems, reactToMenuItem
- */
- void setPopupMenuActive (bool hasMenu);
-
- /** Returns true if the pop-up menu is enabled.
- @see setPopupMenuActive
- */
- bool isPopupMenuActive() const;
-
- //==============================================================================
- /** Returns a string that encapsulates the table's current layout.
-
- This can be restored later using restoreFromString(). It saves the order of
- the columns, the currently-sorted column, and the widths.
-
- @see restoreFromString
- */
- String toString() const;
-
- /** Restores the state of the table, based on a string previously created with
- toString().
-
- @see toString
- */
- void restoreFromString (const String& storedVersion);
-
- //==============================================================================
- /**
- Receives events from a TableHeaderComponent when columns are resized, moved, etc.
-
- You can register one of these objects for table events using TableHeaderComponent::addListener()
- and TableHeaderComponent::removeListener().
-
- @see TableHeaderComponent
- */
- class JUCE_API Listener
- {
- public:
- //==============================================================================
- Listener() = default;
-
- /** Destructor. */
- virtual ~Listener() = default;
-
- //==============================================================================
- /** This is called when some of the table's columns are added, removed, hidden,
- or rearranged.
- */
- virtual void tableColumnsChanged (TableHeaderComponent* tableHeader) = 0;
-
- /** This is called when one or more of the table's columns are resized. */
- virtual void tableColumnsResized (TableHeaderComponent* tableHeader) = 0;
-
- /** This is called when the column by which the table should be sorted is changed. */
- virtual void tableSortOrderChanged (TableHeaderComponent* tableHeader) = 0;
-
- /** This is called when the user begins or ends dragging one of the columns around.
-
- When the user starts dragging a column, this is called with the ID of that
- column. When they finish dragging, it is called again with 0 as the ID.
- */
- virtual void tableColumnDraggingChanged (TableHeaderComponent* tableHeader,
- int columnIdNowBeingDragged);
- };
-
- /** Adds a listener to be informed about things that happen to the header. */
- void addListener (Listener* newListener);
-
- /** Removes a previously-registered listener. */
- void removeListener (Listener* listenerToRemove);
-
- //==============================================================================
- /** This can be overridden to handle a mouse-click on one of the column headers.
-
- The default implementation will use this click to call getSortColumnId() and
- change the sort order.
- */
- virtual void columnClicked (int columnId, const ModifierKeys& mods);
-
- /** This can be overridden to add custom items to the pop-up menu.
-
- If you override this, you should call the superclass's method to add its
- column show/hide items, if you want them on the menu as well.
-
- Then to handle the result, override reactToMenuItem().
-
- @see reactToMenuItem
- */
- virtual void addMenuItems (PopupMenu& menu, int columnIdClicked);
-
- /** Override this to handle any custom items that you have added to the
- pop-up menu with an addMenuItems() override.
-
- If the menuReturnId isn't one of your own custom menu items, you'll need to
- call TableHeaderComponent::reactToMenuItem() to allow the base class to
- handle the items that it had added.
-
- @see addMenuItems
- */
- virtual void reactToMenuItem (int menuReturnId, int columnIdClicked);
-
- //==============================================================================
- /** A set of colour IDs to use to change the colour of various aspects of the TableHeaderComponent.
-
- @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
- */
- enum ColourIds
- {
- textColourId = 0x1003800, /**< The colour for the text in the header. */
- backgroundColourId = 0x1003810, /**< The colour of the table header background.
- It's up to the LookAndFeel how this is used. */
- outlineColourId = 0x1003820, /**< The colour of the table header's outline. */
- highlightColourId = 0x1003830, /**< The colour of the table header background when
- the mouse is over or down above the the table
- header. It's up to the LookAndFeel to use a
- variant of this colour to distinguish between
- the down and hover state. */
- };
-
- //==============================================================================
- /** This abstract base class is implemented by LookAndFeel classes. */
- struct JUCE_API LookAndFeelMethods
- {
- virtual ~LookAndFeelMethods() = default;
-
- virtual void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) = 0;
-
- virtual void drawTableHeaderColumn (Graphics&, TableHeaderComponent&,
- const String& columnName, int columnId,
- int width, int height,
- bool isMouseOver, bool isMouseDown, int columnFlags) = 0;
- };
-
- //==============================================================================
- /** @internal */
- void paint (Graphics&) override;
- /** @internal */
- void mouseMove (const MouseEvent&) override;
- /** @internal */
- void mouseEnter (const MouseEvent&) override;
- /** @internal */
- void mouseExit (const MouseEvent&) override;
- /** @internal */
- void mouseDown (const MouseEvent&) override;
- /** @internal */
- void mouseDrag (const MouseEvent&) override;
- /** @internal */
- void mouseUp (const MouseEvent&) override;
- /** @internal */
- MouseCursor getMouseCursor() override;
-
- /** Can be overridden for more control over the pop-up menu behaviour. */
- virtual void showColumnChooserMenu (int columnIdClicked);
-
- private:
- struct ColumnInfo
- {
- String name;
- int id, propertyFlags, width, minimumWidth, maximumWidth;
- double lastDeliberateWidth;
-
- bool isVisible() const;
- };
-
- OwnedArray<ColumnInfo> columns;
- Array<Listener*> listeners;
- std::unique_ptr<Component> dragOverlayComp;
- class DragOverlayComp;
-
- bool columnsChanged = false, columnsResized = false, sortChanged = false;
- bool menuActive = true, stretchToFit = false;
- int columnIdBeingResized = 0, columnIdBeingDragged = 0, initialColumnWidth = 0;
- int columnIdUnderMouse = 0, draggingColumnOffset = 0, draggingColumnOriginalIndex = 0, lastDeliberateWidth = 0;
-
- ColumnInfo* getInfoForId (int columnId) const;
- int visibleIndexToTotalIndex (int visibleIndex) const;
- void sendColumnsChanged();
- void handleAsyncUpdate() override;
- void beginDrag (const MouseEvent&);
- void endDrag (int finalIndex);
- int getResizeDraggerAt (int mouseX) const;
- void updateColumnUnderMouse (const MouseEvent&);
- void setColumnUnderMouse (int columnId);
- void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth);
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableHeaderComponent)
- };
-
-
- } // namespace juce
|