/* * This source file is part of libRocket, the HTML/CSS Interface Middleware * * For the latest information, see http://www.librocket.com * * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #ifndef ROCKETCONTROLSELEMENTDATAGRIDROW_H #define ROCKETCONTROLSELEMENTDATAGRIDROW_H #include "Header.h" #include "DataSourceListener.h" #include "DataQuery.h" #include "../Core/Element.h" #include namespace Rocket { namespace Controls { class ElementDataGrid; /** Class for rows inside a data table. Used for both the header and the individual rows. @author Robert Curry */ class ROCKETCONTROLS_API ElementDataGridRow : public Core::Element, public DataSourceListener { friend class ElementDataGrid; public: ElementDataGridRow(const Rocket::Core::String& tag); virtual ~ElementDataGridRow(); void Initialise(ElementDataGrid* parent_grid, ElementDataGridRow* parent_row = NULL, int child_index = -1, ElementDataGridRow* header_row = NULL, int depth = -1); void SetChildIndex(int child_index); int GetDepth(); void SetDataSource(const Rocket::Core::String& data_source_name); /// Checks dirty children and cells, and loads them if necessary. /// @return True if any children were updated. bool UpdateChildren(); /// Returns the number of children that aren't dirty (have been loaded) int GetNumLoadedChildren(); // Removes all the child cells and fetches them again from the data // source. void RefreshRows(); /// Returns whether this row is expanded or not. bool IsRowExpanded(); /// Shows all of this row's descendants. void ExpandRow(); /// Hides all of this row's descendants. void CollapseRow(); /// Expands the row if collapsed, or collapses the row if expanded. void ToggleRow(); /// Returns the index of this row, relative to its parent. int GetParentRelativeIndex(); /// Returns the index of this row, relative to the table rather than its parent. int GetTableRelativeIndex(); /// Returns the parent row of this row. ElementDataGridRow* GetParentRow(); /// Returns the grid that this row belongs to. ElementDataGrid* GetParentGrid(); protected: virtual void OnDataSourceDestroy(DataSource* data_source); virtual void OnRowAdd(DataSource* data_source, const Rocket::Core::String& table, int first_row_added, int num_rows_added); virtual void OnRowRemove(DataSource* data_source, const Rocket::Core::String& table, int first_row_removed, int num_rows_removed); virtual void OnRowChange(DataSource* data_source, const Rocket::Core::String& table, int first_row_changed, int num_rows_changed); virtual void OnRowChange(DataSource* data_source, const Rocket::Core::String& table); private: typedef std::queue< ElementDataGridRow* > RowQueue; typedef std::vector< ElementDataGridRow* > RowList; // Called when a row change (addition or removal) occurs in one of our // children. Causes the table row index to be dirtied on all following // children. void ChildChanged(int child_index); // Checks if any columns are dependent on the number of children // present, and refreshes them from the data source if they are. void RefreshChildDependentCells(); // Forces the row to recalculate its relative table index the next time // it is requested. void DirtyTableRelativeIndex(); // Works out what the table relative index is for a given child. int GetChildTableRelativeIndex(int child_index); // Adds children underneath this row, and fetches their contents (and // possible children) from the row's data source. If first_row is left // as the default -1, the rows are appended at the end of the list. void AddChildren(int first_row_added = -1, int num_rows_added = 1); // Removes this rows children, and their children, etc, from the table. // If the num_rows_removed parameter is left as the -1 default, it'll // default to the rest of the children after the first row. void RemoveChildren(int first_row_removed = 0, int num_rows_removed = -1); // Marks children as dirty and dispatches the event. void ChangeChildren(int first_row_changed = 0, int num_rows_changed = -1); // Returns the number of rows under this row (children, grandchildren, etc) int GetNumDescendants(); // Adds or refreshes the cell contents, and undirties the row's cells. void Load(const Rocket::Controls::DataQuery& row_information); // Finds all children that have cell information missing (either though being // refreshed or not being loaded yet) and reloads them. void LoadChildren(float time_slice); // Loads a specific set of children. Called by the above function. void LoadChildren(int first_row_to_load, int num_rows_to_load, Rocket::Core::Time time_slice); // If the cells need reloading, this takes care of it. If any children // need updating, they are added to the queue. void UpdateCellsAndChildren(RowQueue& dirty_rows); // Sets the dirty_cells flag on this row, and lets our ancestors know. void DirtyCells(); // Sets the dirty children flag on this row and the row's ancestors. void DirtyRow(); // This row has one or more cells that need loading. bool dirty_cells; // This row has one or more children that have either dirty flag set. bool dirty_children; // Shows this row, and, if this was was expanded before it was hidden, its children as well. void Show(); // Hides this row and all descendants. void Hide(); bool row_expanded; int table_relative_index; bool table_relative_index_dirty; ElementDataGrid* parent_grid; ElementDataGridRow* parent_row; int child_index; int depth; RowList children; // The data source and table that the children are fetched from. DataSource* data_source; Rocket::Core::String data_table; }; } } #endif