|
| 1 | +#include <Wt/WStandardItem> |
| 2 | +#include <Wt/WStandardItemModel> |
| 3 | +#include <Wt/WStringListModel> |
| 4 | +#include <Wt/WTableView> |
| 5 | +#include <Wt/WItemDelegate> |
| 6 | +#include <Wt/WContainerWidget> |
| 7 | +#include <Wt/WComboBox> |
| 8 | + |
| 9 | +/* |
| 10 | + * This delegate demonstrates how to override the editing behaviour of a |
| 11 | + * table cell. |
| 12 | + * |
| 13 | + * It takes a list of possible items on construction and, when edited, saves |
| 14 | + * the selected item from the list to the Wt::DisplayRole in the model for |
| 15 | + * Wt::WItemDelegate to render. |
| 16 | + * It also saves the items index for future editing (rather than each time |
| 17 | + * searching the item in the list). This is done using the general purpose |
| 18 | + * Wt::UserRole in the model. |
| 19 | + */ |
| 20 | +class ComboDelegate : public Wt::WItemDelegate { |
| 21 | +public: |
| 22 | + ComboDelegate(Wt::WStringListModel* items) |
| 23 | + : items_(items) |
| 24 | + {} |
| 25 | + |
| 26 | + void setModelData(const boost::any &editState, Wt::WAbstractItemModel* model, |
| 27 | + const Wt::WModelIndex &index) const |
| 28 | + { |
| 29 | + int stringIdx = Wt::asNumber(editState); |
| 30 | + model->setData(index, stringIdx, Wt::UserRole); |
| 31 | + model->setData(index, items_->stringList()[stringIdx], Wt::DisplayRole); |
| 32 | + } |
| 33 | + |
| 34 | + boost::any editState(Wt::WWidget* editor) const |
| 35 | + { |
| 36 | + Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*> |
| 37 | + (dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0)); |
| 38 | + return combo->currentIndex(); |
| 39 | + } |
| 40 | + |
| 41 | + void setEditState(Wt::WWidget* editor, const boost::any &value) const |
| 42 | + { |
| 43 | + Wt::WComboBox* combo = dynamic_cast<Wt::WComboBox*> |
| 44 | + (dynamic_cast<Wt::WContainerWidget*>(editor)->widget(0)); |
| 45 | + combo->setCurrentIndex(Wt::asNumber(value)); |
| 46 | + } |
| 47 | + |
| 48 | +protected: |
| 49 | + virtual Wt::WWidget* createEditor(const Wt::WModelIndex &index, |
| 50 | + Wt::WFlags<Wt::ViewItemRenderFlag> flags) const |
| 51 | + { |
| 52 | + Wt::WContainerWidget* container = new Wt::WContainerWidget(); |
| 53 | + Wt::WComboBox* combo = new Wt::WComboBox(container); |
| 54 | + combo->setModel(items_); |
| 55 | + combo->setCurrentIndex(Wt::asNumber(index.data(Wt::UserRole))); |
| 56 | + |
| 57 | + combo->changed().connect(boost::bind(&ComboDelegate::doCloseEditor, this, |
| 58 | + container, true)); |
| 59 | + combo->enterPressed().connect(boost::bind(&ComboDelegate::doCloseEditor, |
| 60 | + this, container, true)); |
| 61 | + combo->escapePressed().connect(boost::bind(&ComboDelegate::doCloseEditor, |
| 62 | + this, container, false)); |
| 63 | + |
| 64 | + return container; |
| 65 | + } |
| 66 | + |
| 67 | +private: |
| 68 | + Wt::WStringListModel* items_; |
| 69 | + |
| 70 | + void doCloseEditor(Wt::WWidget *editor, bool save) const |
| 71 | + { |
| 72 | + closeEditor().emit(editor, save); |
| 73 | + } |
| 74 | +}; |
| 75 | + |
| 76 | +SAMPLE_BEGIN(ComboDelegateTable) |
| 77 | +Wt::WTableView *table = new Wt::WTableView(); |
| 78 | + |
| 79 | +// create model |
| 80 | +std::vector<Wt::WString> options; |
| 81 | +options.push_back("apples"); |
| 82 | +options.push_back("pears"); |
| 83 | +options.push_back("bananas"); |
| 84 | +options.push_back("cherries"); |
| 85 | + |
| 86 | +Wt::WStandardItemModel *model = new Wt::WStandardItemModel(table); |
| 87 | +for (unsigned i=0; i < 2; i++) { |
| 88 | + for (unsigned j=0; j < 2; j++) { |
| 89 | + Wt::WStandardItem *item = new Wt::WStandardItem(); |
| 90 | + item->setData(0, Wt::UserRole); |
| 91 | + item->setData(options[0], Wt::DisplayRole); |
| 92 | + item->setFlags(Wt::ItemIsEditable); |
| 93 | + model->setItem(i, j, item); |
| 94 | + } |
| 95 | +} |
| 96 | + |
| 97 | +// create table |
| 98 | +table->setModel(model); |
| 99 | +table->setEditTriggers(Wt::WAbstractItemView::SingleClicked); |
| 100 | +Wt::WStringListModel* slModel = new Wt::WStringListModel(table); |
| 101 | +slModel->setStringList(options); |
| 102 | +ComboDelegate* customdelegate = new ComboDelegate(slModel); |
| 103 | +table->setItemDelegate(customdelegate); |
| 104 | + |
| 105 | +table->setSortingEnabled(false); |
| 106 | +table->setColumnResizeEnabled(false); |
| 107 | +table->setRowHeight(40); |
| 108 | +table->setHeaderHeight(0); |
| 109 | + |
| 110 | +const int WIDTH = 120; |
| 111 | +for (int i = 0; i < table->model()->columnCount(); ++i) |
| 112 | + table->setColumnWidth(i, WIDTH); |
| 113 | +table->setWidth((WIDTH + 7) * table->model()->columnCount() + 2); |
| 114 | + |
| 115 | +SAMPLE_END(return table) |
0 commit comments