Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ add_library(nanogui-obj OBJECT
include/nanogui/tabheader.h src/tabheader.cpp
include/nanogui/tabwidget.h src/tabwidget.cpp
include/nanogui/glcanvas.h src/glcanvas.cpp
include/nanogui/table.h src/table.cpp
include/nanogui/formhelper.h
include/nanogui/toolbutton.h
include/nanogui/opengl.h
Expand Down
1 change: 1 addition & 0 deletions include/nanogui/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ extern NANOGUI_EXPORT std::string
file_dialog(const std::vector<std::pair<std::string, std::string>> &filetypes,
bool save);

bool isPointInsideRect(const Vector2i& p, const Vector4i& r);
/**
* \brief Open a native file open dialog, which allows multiple selection.
*
Expand Down
3 changes: 3 additions & 0 deletions include/nanogui/label.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ NAMESPACE_BEGIN(nanogui)
*/
class NANOGUI_EXPORT Label : public Widget {
public:
enum TextAlign { alLeft=0, alCenter, alRight };
Label(Widget *parent, const std::string &caption,
const std::string &font = "sans", int fontSize = -1);

Expand All @@ -43,6 +44,7 @@ class NANOGUI_EXPORT Label : public Widget {
Color color() const { return mColor; }
/// Set the label color
void setColor(const Color& color) { mColor = color; }
void setTextAlign(TextAlign align) { mTextAlign = align; }

/// Set the \ref Theme used to draw this widget
virtual void setTheme(Theme *theme) override;
Expand All @@ -59,6 +61,7 @@ class NANOGUI_EXPORT Label : public Widget {
std::string mCaption;
std::string mFont;
Color mColor;
TextAlign mTextAlign = alLeft;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
Expand Down
283 changes: 283 additions & 0 deletions include/nanogui/table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
#pragma once

#include <nanogui/widget.h>
#include <bitset>
#include <vector>

NAMESPACE_BEGIN(nanogui)

class ScrollBar;
class TextBox;

class NANOGUI_EXPORT Table : public Widget
{
public:
//! modes for ordering used when a column header is clicked
enum ColumnOrder
{
//! Do not use ordering
coNone,

//! Send a EGET_TABLE_HEADER_CHANGED message when a column header is clicked.
coCustom,

//! Sort it ascending by it's ascii value like: a,b,c,...
coAscending,

//! Sort it descending by it's ascii value like: z,x,y,...
coDescending,

//! Sort it ascending on first click, descending on next, etc
coAscendingDescending,

//! Not used as mode, only to get maximum value for this enum
coCount
};

enum RowOrder
{
//! No element ordering
roNone,

//! Elements are ordered from the smallest to the largest.
roAscending,

//! Elements are ordered from the largest to the smallest.
roDescending,

//! this value is not used, it only specifies the amount of default ordering types
//! available.
roCount
};

enum DrawFlag
{
drawRows = 0,
drawColumns = 1,
drawActiveRow = 2,
drawRowBackground = 3,
drawBorder = 4,
drawCount
} ;
//! constructor
Table( Widget* parent,
const std::string& id, const Vector4i& rectangle, bool clip=true,
bool drawBack=false, bool moveOverSelect=true);

//! destructor
virtual ~Table();

//! Adds a column
//! If columnIndex is outside the current range, do push new colum at the end
virtual void addColumn(const std::string& caption, uint32_t columnIndex=0xffffffff);

//! remove a column from the table
virtual void removeColumn(uint32_t columnIndex);

//! Returns the number of columns in the table control
virtual int getColumnCount() const;

//! Makes a column active. This will trigger an ordering process.
/** \param idx: The id of the column to make active.
\return True if successful. */
virtual bool setActiveColumn(int columnIndex, bool doOrder=false);

//! Returns which header is currently active
virtual int getActiveColumn() const;

bool scrollEvent(const Vector2i &p, const Vector2f &rel) override;

//! Returns the ordering used by the currently active column
virtual RowOrder getActiveColumnOrdering() const;

//! set a column width
virtual void setColumnWidth(uint32_t columnIndex, uint32_t width);

//! returns column width
virtual uint32_t getColumnWidth(uint32_t columnIndex) const;

//! columns can be resized by drag 'n drop
virtual void setResizableColumns(bool resizable);

//! can columns be resized by dran 'n drop?
virtual bool hasResizableColumns() const;

//! This tells the table control which ordering mode should be used when
//! a column header is clicked.
/** \param columnIndex: The index of the column header.
\param state: If true, a message will be sent and you can order the table data as you whish.*/
//! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING
virtual void setColumnOrdering(uint32_t columnIndex, ColumnOrder mode);

//! Returns which row is currently selected
virtual int getSelected() const;

//! set wich row is currently selected
virtual void setSelected( int index );

virtual ScrollBar* getVerticalScrolBar();

virtual int getSelectedColumn() const;

//! Returns amount of rows in the tabcontrol
virtual int getRowCount() const;

//! adds a row to the table
/** \param rowIndex: zero based index of rows. The row will be
inserted at this position. If a row already exists
there, it will be placed after it. If the row is larger
than the actual number of rows by more than one, it
won't be created. Note that if you create a row that is
not at the end, there might be performance issues*/
virtual uint32_t addRow(uint32_t rowIndex);

//! Remove a row from the table
virtual void removeRow(uint32_t rowIndex);

//! clear the table rows, but keep the columns intact
virtual void clearRows();

//! Swap two row positions. This is useful for a custom ordering algo.
virtual void swapRows(uint32_t rowIndexA, uint32_t rowIndexB);

//! This tells the table to start ordering all the rows. You
//! need to explicitly tell the table to reorder the rows when
//! a new row is added or the cells data is changed. This makes
//! the system more flexible and doesn't make you pay the cost
//! of ordering when adding a lot of rows.
//! \param columnIndex: When set to -1 the active column is used.
virtual void orderRows(int columnIndex=-1, RowOrder mode=roNone);


//! Set the text of a cell
virtual void setCellText(uint32_t rowIndex, uint32_t columnIndex, const std::string& text);

//! Set element of a cell
virtual void setCellElement(uint32_t rowIndex, uint32_t columnIndex, Widget* elm );

//! Remove element from cell
virtual void removeCellElement(uint32_t rowIndex, uint32_t columnIndex);

//! Get element from cell
virtual Widget* getCellElement(uint32_t rowIndex, uint32_t columnIndex) const;

//! Set the text of a cell, and set a color of this cell.
virtual void setCellText(uint32_t rowIndex, uint32_t columnIndex, const std::string& text, const Color& color);

//! Set the data of a cell
//! data will not be serialized.
virtual void setCellDataptr(uint32_t rowIndex, uint32_t columnIndex, uintptr_t data);

//! Set the color of a cell text
virtual void setCellTextColor(uint32_t rowIndex, uint32_t columnIndex, const Color& color);

//! Get the text of a cell
virtual std::string getCellText(uint32_t rowIndex, uint32_t columnIndex ) const;

//! Get the data of a cell
virtual uintptr_t getCellDataptr(uint32_t rowIndex, uint32_t columnIndex ) const;

//! clears the table, deletes all items in the table
virtual void clear();

//! clears the contents int table, deletes all cell elements in the table
virtual void clearContent();

//! called if an event happened.
//virtual bool onEvent(const NEvent &event);

//! draws the element and its children
virtual void draw(NVGcontext* ctx);

//! Set flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout
virtual void setDrawFlag( DrawFlag flag, bool enabled=true );

//! Get the flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout
virtual bool isFlag( DrawFlag flag ) const;

//!
virtual void setItemHeight(int height);

//!
virtual void beforePaint(NVGcontext* ctx);

bool mouseButtonEvent(const Vector2i &pp, int button, bool down, int modifiers) override;
bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;

//! Writes attributes of the object.
//! Implement this to expose the attributes of your scene node animator for
//! scripting languages, editors, debuggers or xml serialization purposes.
//virtual void save( core::VariantArray* out ) const;

//! Reads attributes of the object.
//! Implement this to set the attributes of your scene node animator for
//! scripting languages, editors, debuggers or xml deserialization purposes.
//virtual void load( core::VariantArray* in );

virtual void removeChild(Widget* child);

protected:
virtual void _refreshControls();
virtual void _recalculateScrollBars();
void _startEditCell(int col, int row);
void _finishEditCell();

private:
void _selectNew(int xpos, int ypos, bool lmb, bool onlyHover);
bool _selectColumnHeader(int xpos, int ypos);
bool _dragColumnStart(int xpos, int ypos);
bool _dragColumnUpdate(int xpos);
void _recalculateHeights();
void _recalculateColumnsWidth();

int _getCurrentColumn(int xpos, int ypos );
void _recalculateCells();

bool _clip;
bool _moveOverSelect;
bool _selecting;
int _currentResizedColumn;
int _resizeStart;
bool _resizableColumns;

int _itemHeight;
int _overItemHeight;
int _totalItemHeight;
int _totalItemWidth;
int _selectedRow, _selectedColumn;
int _editedRow, _editedColumn;
int _cellHeightPadding;
int _cellWidthPadding;
int _activeTab;
RowOrder _currentOrdering;

class Cell;
class Column;
class HidingElement;
struct Row { std::vector<Cell*> items; };

typedef std::vector<Column*> Columns;
typedef std::vector<Row> Rows;
typedef std::bitset<16> DrawFlags;

DrawFlags _drawflags;
Columns _columns;
Rows _rows;
std::string _font = "sans";

Widget* _header;
TextBox* _edit = nullptr;
Widget* _itemsArea;
ScrollBar* _verticalScrollBar;
ScrollBar* _horizontalScrollBar;
bool _needRefreshCellsGeometry;
uint32_t _cellLastTimeClick;

int _vscrollsize = 0;
int _hscrollsize = 0;

Cell* _getCell(int row, int col);
};

NAMESPACE_END(nanogui)

2 changes: 2 additions & 0 deletions include/nanogui/textbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class NANOGUI_EXPORT TextBox : public Widget {

/// Sets the callback to execute when the value of this TextBox has changed.
void setCallback(const std::function<bool(const std::string& str)> &callback) { mCallback = callback; }
void setComitCallback(const std::function<void(Widget*)> &callback) { mComitCallback = callback; }

virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override;
virtual bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
Expand Down Expand Up @@ -121,6 +122,7 @@ class NANOGUI_EXPORT TextBox : public Widget {
std::string mFormat;
int mUnitsImage;
std::function<bool(const std::string& str)> mCallback;
std::function<void(Widget*)> mComitCallback;
bool mValidFormat;
std::string mValueTemp;
std::string mPlaceholder;
Expand Down
31 changes: 31 additions & 0 deletions include/nanogui/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,46 @@ class NANOGUI_EXPORT Widget : public Object {

/// Return the position relative to the parent widget
const Vector2i &position() const { return mPos; }
const int right() const { return mPos.x() + mSize.x(); }
const int left() const { return mPos.x(); }
/// Set the position relative to the parent widget
void setPosition(const Vector2i &pos) { mPos = pos; }
void setPosition(int x, int y) { mPos = Vector2i(x, y); }

void setGeometry(const Vector4i &vec) {
setPosition(vec.x(), vec.y());
setSize(vec.z() - vec.x(), vec.w() - vec.y());
}

bool sendChildToBack(Widget* child);
bool sendToBack();

/// Return the absolute position on screen
Vector2i absolutePosition() const {
return mParent ?
(parent()->absolutePosition() + mPos) : mPos;
}

Vector4i absoluteRect() const {
Vector2i ap = absolutePosition();
return Vector4i(ap.x(), ap.y(), ap.x() + width(), ap.y() + height());
}

Widget *findWidget(const std::string& id, bool inchildren = true);
Widget *findWidget(std::function<bool(Widget*)> cond, bool inchildren = true);

Widget *findWidgetGlobal(const std::string& id);
Widget *findWidgetGlobal(std::function<bool(Widget*)> cond);

virtual std::string wtypename() const;

template<typename RetClass>
RetClass *findWidgetGlobal(const std::string& id)
{
Widget* f = findWidgetGlobal(id);
return f ? f->cast<RetClass>() : nullptr;
}

/// Return the size of the widget
const Vector2i &size() const { return mSize; }
/// set the size of the widget
Expand Down
5 changes: 5 additions & 0 deletions src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

NAMESPACE_BEGIN(nanogui)

bool isPointInsideRect(const Vector2i& p, const Vector4i& r)
{
return (p.x() >= r.x() && p.y() >= r.y() && p.x() <= r.z() && p.y() <= r.w());
}

extern std::map<GLFWwindow *, Screen *> __nanogui_screens;

#if defined(__APPLE__)
Expand Down
Loading