// Sets the index of the selection. If the new index lies outside of the bounds, it will be clamped. void WidgetDropDown::SetSelection(int selection, bool force) { Rocket::Core::String new_value; if (selection < 0 || selection >= (int) options.size()) { selection = -1; } else { new_value = options[selection].GetValue(); } if (force || selection != selected_option || value != new_value) { selected_option = selection; value = new_value; Rocket::Core::String value_rml; if (selected_option >= 0) options[selected_option].GetElement()->GetInnerRML(value_rml); value_element->SetInnerRML(value_rml); value_layout_dirty = true; Rocket::Core::Dictionary parameters; parameters.Set("value", value); parent_element->DispatchEvent("change", parameters); } }
void ElementDataGridRow::RemoveChildren(int first_row_removed, int num_rows_removed) { if (num_rows_removed == -1) { num_rows_removed = (int)children.size() - first_row_removed; } // prevent relayout of the document while removing rows Core::ElementDocument* document = parent_grid->GetOwnerDocument(); document->LockLayout(true); for (int i = num_rows_removed - 1; i >= 0; i--) { children[first_row_removed + i]->RemoveChildren(); parent_grid->RemoveRows(children[first_row_removed + i]->GetTableRelativeIndex()); } children.erase(children.begin() + first_row_removed, children.begin() + (first_row_removed + num_rows_removed)); for (int i = first_row_removed; i < (int) children.size(); i++) { children[i]->SetChildIndex(i); children[i]->DirtyTableRelativeIndex(); } document->LockLayout(false); Rocket::Core::Dictionary parameters; parameters.Set("first_row_removed", GetChildTableRelativeIndex(first_row_removed)); parameters.Set("num_rows_removed", num_rows_removed); parent_grid->DispatchEvent("rowremove", parameters); }
void ElementTabSet::SetActiveTab(int tab_index) { // Update display if the tab has changed if (tab_index != active_tab) { Core::Element* tabs = GetChildByTag("tabs"); Core::Element* old_tab = tabs->GetChild(active_tab); Core::Element* new_tab = tabs->GetChild(tab_index); if (old_tab) old_tab->SetPseudoClass("selected", false); if (new_tab) new_tab->SetPseudoClass("selected", true); Core::Element* windows = GetChildByTag("panels"); Core::Element* old_window = windows->GetChild(active_tab); Core::Element* new_window = windows->GetChild(tab_index); if (old_window) old_window->SetProperty("display", "none"); if (new_window) new_window->SetProperty("display", "inline-block"); active_tab = tab_index; Rocket::Core::Dictionary parameters; parameters.Set("tab_index", active_tab); DispatchEvent("tabchange", parameters); } }
void ElementDataGridRow::RemoveChildren(int first_row_removed, int num_rows_removed) { if (num_rows_removed == -1) { num_rows_removed = (int)children.size() - first_row_removed; } for (int i = num_rows_removed - 1; i >= 0; i--) { children[first_row_removed + i]->RemoveChildren(); parent_grid->RemoveRows(children[first_row_removed + i]->GetTableRelativeIndex()); } children.erase(children.begin() + first_row_removed, children.begin() + (first_row_removed + num_rows_removed)); for (int i = first_row_removed; i < (int) children.size(); i++) { children[i]->SetChildIndex(i); children[i]->DirtyTableRelativeIndex(); } Rocket::Core::Dictionary parameters; parameters.Set("first_row_removed", GetChildTableRelativeIndex(first_row_removed)); parameters.Set("num_rows_removed", num_rows_removed); parent_grid->DispatchEvent("rowremove", parameters); }
void ElementDataGridRow::ChangeChildren(int first_row_changed, int num_rows_changed) { for (int i = first_row_changed; i < first_row_changed + num_rows_changed; i++) children[i]->DirtyCells(); Rocket::Core::Dictionary parameters; parameters.Set("first_row_changed", GetChildTableRelativeIndex(first_row_changed)); parameters.Set("num_rows_changed", num_rows_changed); parent_grid->DispatchEvent("rowchange", parameters); }
// Adds children underneath this row, and fetches their contents (and possible // children) from the row's data source. void ElementDataGridRow::AddChildren(int first_row_added, int num_rows_added) { if (first_row_added == -1) { first_row_added = (int)children.size(); } // prevent relayout of the document while adding rows Core::ElementDocument* document = parent_grid->GetOwnerDocument(); document->LockLayout(true); // We need to make a row for each new child, then pass through the cell // information and the child's data source (if one exists.) if (data_source) { for (int i = 0; i < num_rows_added; i++) { int row_index = first_row_added + i; // Make a new row: ElementDataGridRow* new_row = parent_grid->AddRow(this, row_index); children.insert(children.begin() + row_index, new_row); if (!row_expanded) { new_row->SetProperty("display", "none"); } } for (int i = first_row_added + num_rows_added; i < (int)children.size(); i++) { children[i]->SetChildIndex(i); children[i]->DirtyTableRelativeIndex(); } if (parent_row) { parent_row->ChildChanged(child_index); } } document->LockLayout(false); RefreshChildDependentCells(); DirtyRow(); Rocket::Core::Dictionary parameters; parameters.Set("first_row_added", GetChildTableRelativeIndex(first_row_added)); parameters.Set("num_rows_added", num_rows_added); parent_grid->DispatchEvent("rowadd", parameters); }
// Checks for necessary functional changes in the control as a result of changed attributes. bool InputTypeCheckbox::OnAttributeChange(const Core::AttributeNameList& changed_attributes) { // Check if maxlength has been defined. if (changed_attributes.find("checked") != changed_attributes.end()) { bool checked = element->HasAttribute("checked"); element->SetPseudoClass("checked", checked); Rocket::Core::Dictionary parameters; parameters.Set("value", Rocket::Core::String(checked ? GetValue() : "")); element->DispatchEvent("change", parameters); } return true; }
// Submits the form. void ElementForm::Submit(const Rocket::Core::String& name, const Rocket::Core::String& submit_value) { Rocket::Core::Dictionary values; if (name.Empty()) values.Set("submit", submit_value); else values.Set(name, submit_value); Core::ElementList form_controls; Core::ElementUtilities::GetElementsByTagName(form_controls, this, "input"); Core::ElementUtilities::GetElementsByTagName(form_controls, this, "textarea"); Core::ElementUtilities::GetElementsByTagName(form_controls, this, "select"); Core::ElementUtilities::GetElementsByTagName(form_controls, this, "dataselect"); for (size_t i = 0; i < form_controls.size(); i++) { ElementFormControl* control = rocket_dynamic_cast< ElementFormControl* >(form_controls[i]); if (!control) continue; // Skip disabled controls. if (control->IsDisabled()) continue; // Only process controls that should be submitted. if (!control->IsSubmitted()) continue; Rocket::Core::String control_name = control->GetName(); Rocket::Core::String control_value = control->GetValue(); // Skip over unnamed form controls. if (control_name.Empty()) continue; // If the item already exists, append to it. Rocket::Core::Variant* value = values.Get(control_name); if (value != NULL) value->Set(value->Get< Rocket::Core::String >() + ", " + control_value); else values.Set< Rocket::Core::String >(control_name, control_value); } DispatchEvent("submit", values); }
// Adds a column to the table. void ElementDataGrid::AddColumn(const Rocket::Core::String& fields, const Rocket::Core::String& formatter, float initial_width, Core::Element* header_element) { Column column; Rocket::Core::StringUtilities::ExpandString(column.fields, fields); column.formatter = DataFormatter::GetDataFormatter(formatter); column.header = header; column.current_width = initial_width; column.refresh_on_child_change = false; // The header elements are added to the header row at the top of the table. if (header_element) { header_element->SetProperty("display", "inline-block"); // Push all the width properties from the column onto the header element. Rocket::Core::String width = header_element->GetAttribute<Rocket::Core::String>("width", "100%"); header_element->SetProperty("width", width); header->AppendChild(header_element); } // Add the fields that this column requires to the concatenated string of all column fields. for (size_t i = 0; i < column.fields.size(); i++) { // Don't append the depth or num_children fields, as they're handled by the row. if (column.fields[i] == Rocket::Controls::DataSource::NUM_CHILDREN) { column.refresh_on_child_change = true; } else if (column.fields[i] != Rocket::Controls::DataSource::DEPTH) { if (!column_fields.Empty()) { column_fields.Append(","); } column_fields.Append(column.fields[i]); } } columns.push_back(column); Rocket::Core::Dictionary parameters; parameters.Set("index", (int)(columns.size() - 1)); DispatchEvent("columnadd", parameters); }
void RocketModule::keyEvent( int contextId, int key, bool pressed ) { // DEBUG #if 0 if( key >= 32 && key <= 126 ) Com_Printf("**KEYEVENT CHAR %c\n", key & 0xff ); else Com_Printf("**KEYEVENT KEY %d\n", key ); #endif if( key == K_MOUSE1DBLCLK ) return; // Rocket handles double click internally auto *context = contextForId( contextId ); Element *element = context->GetFocusElement(); int mod = KeyConverter::getModifiers(); // send the blur event, to the current focused element, when ESC key is pressed if( ( key == K_ESCAPE ) && element ) element->Blur(); if( element && ( element->GetTagName() == "keyselect" ) ) { if( pressed ) { Rocket::Core::Dictionary parameters; parameters.Set( "key", key ); element->DispatchEvent( "keyselect", parameters ); } } else if( key >= K_MOUSE1 && key <= K_MOUSE8 ) // warsow sends mousebuttons as keys { if( pressed ) context->ProcessMouseButtonDown( key-K_MOUSE1, mod ); else context->ProcessMouseButtonUp( key-K_MOUSE1, mod ); } else if( key == K_MWHEELDOWN ) // and ditto for wheel { context->ProcessMouseWheel( 1, mod ); } else if( key == K_MWHEELUP ) { context->ProcessMouseWheel( -1, mod ); } else { if( ( key == K_A_BUTTON ) || ( key == K_DPAD_CENTER ) ) { if( pressed ) context->ProcessMouseButtonDown( 0, mod ); else context->ProcessMouseButtonUp( 0, mod ); } else { int rkey = KeyConverter::toRocketKey( key ); if( key == K_B_BUTTON ) { rkey = Rocket::Core::Input::KI_ESCAPE; if( element ) element->Blur(); } if( rkey != 0 ) { if( pressed ) context->ProcessKeyDown( Rocket::Core::Input::KeyIdentifier( rkey ), mod ); else context->ProcessKeyUp( Rocket::Core::Input::KeyIdentifier( rkey ), mod ); } } } }
void RocketModule::keyEvent( int key, bool pressed ) { KeyConverter keyconv; int mod; // DEBUG #if 0 if( key >= 32 && key <= 126 ) Com_Printf("**KEYEVENT CHAR %c\n", key & 0xff ); else Com_Printf("**KEYEVENT KEY %d\n", key ); #endif mod = keyconv.getModifiers(); // warsow sends mousebuttons as keys if( key >= K_MOUSE1 && key <= K_MOUSE8 ) { if( pressed ) context->ProcessMouseButtonDown( key-K_MOUSE1, mod ); else context->ProcessMouseButtonUp( key-K_MOUSE1, mod ); } // and ditto for wheel else if( key == K_MWHEELDOWN ) { context->ProcessMouseWheel( KI_MWHEELDOWN, mod ); } else if( key == K_MWHEELUP ) { context->ProcessMouseWheel( KI_MWHEELUP, mod ); } else { Element *element = context->GetFocusElement(); // send the blur event, to the current focused element, // when ESC key is pressed if( ( key == K_ESCAPE ) && element ) element->Blur(); if( pressed && element && ( element->GetTagName() == "keyselect" ) ) { Rocket::Core::Dictionary parameters; parameters.Set( "key", key ); element->DispatchEvent( "keyselect", parameters ); } else { int rkey = keyconv.toRocketKey( key ); if( rkey != 0 ) { if( pressed ) context->ProcessKeyDown( Rocket::Core::Input::KeyIdentifier( rkey ), keyconv.getModifiers() ); else context->ProcessKeyUp( Rocket::Core::Input::KeyIdentifier( rkey ), keyconv.getModifiers() ); } } } }
TEST_F( libRocketDataGridTest, UIDataViewList ) { Point2i pos1(60,25); std::string doc_file1 = "dataview.rml"; UIDataViewList store1; EXPECT_EQ( true, store1.set_context(&this->desktop) ); EXPECT_EQ( true, store1.load_document_file( doc_file1 ) ) << this->test_set() << " object should not be invalid; is the context and document file valid?"; // Ensure that the visual debugger's beacon (err icon) appears on-screen. Rocket::Core::Log::Message( Rocket::Core::Log::LT_ASSERT, "Hello, world!" ); this->model.reset( new CardsPageDataSource("cards_db") ); this->db.reset( new CardCollection() ); EXPECT_TRUE( model != nullptr ); EXPECT_TRUE( db != nullptr ); EXPECT_EQ( true, db->load_db() ) << "Could not initialize nom::CardsPageDataSource data interface."; CardList deck; CardList cards = db->cards(); // Load in the entire cards database for( auto itr = cards.begin(); itr != cards.end(); ++itr ) { deck.push_back( *itr ); } // Deck of cards for the data source model->append_cards( deck ); store1.show(); EXPECT_TRUE( store1.set_column_title(1, "CARDS P. " + std::to_string(model->page() + 1) ) ); EXPECT_EQ( true, store1.visible() ); EXPECT_EQ( pos1, store1.position() ); // Default values sanity EXPECT_EQ( "cards", model->table_name() ); EXPECT_EQ( 11, model->per_page() ); EXPECT_EQ( 0, model->page() ); EXPECT_EQ( 10, model->map_page_row( 10, 0 ) ) << "Selection should be between 0..11"; EXPECT_EQ( 2, model->map_page_row( 13, 1 ) ) << "Selection should be between 0..11"; EXPECT_EQ( 10, model->map_page_row( 21, 1 ) ) << "Selection should be between 0..11"; EXPECT_EQ( "CARDS P. 1", store1.column_title(1) ); EXPECT_EQ( "NUM.", store1.column_title(2) ); store1.register_event_listener( store1.document(), "keydown", new nom::UIEventListener( [&] ( Rocket::Core::Event& ev ) { on_keydown( ev, &store1, db, model, this->phand ); } )); store1.register_event_listener( store1.document(), "mouseup", new nom::UIEventListener( [&] ( Rocket::Core::Event& ev ) { on_mouseup( ev, &store1, db, model, this->phand ); } )); // Synthesized user input events; we hope to capture these before the end of // the first frame Rocket::Core::Element* target = nullptr; Rocket::Core::Dictionary lclick; Rocket::Core::Dictionary rclick; lclick.Set("button","0"); // Left click rclick.Set("button","1"); // Left click // We must update the context before our cards model is filled this->desktop.update(); target = store1.document()->GetElementById("Geezard"); if( target ) { target->DispatchEvent("mouseup", lclick); // Should have zero cards remaining } target = store1.document()->GetElementById("Red Bat"); if( target ) { target->DispatchEvent("mouseup", lclick); target->DispatchEvent("mouseup", lclick); target->DispatchEvent("mouseup", lclick); // Should have one cards remaining } target = store1.document()->GetElementById("Red Bat"); if( target ) { target->DispatchEvent("mouseup", rclick); // Should have two cards remaining } target = store1.document()->GetElementById("Cockatrice"); if( target ) { target->DispatchEvent("mouseup", lclick); target->DispatchEvent("mouseup", lclick); target->DispatchEvent("mouseup", lclick); // Should have zero cards remaining } // NOM_LOG_INFO( NOM_LOG_CATEGORY_TEST, store1.dump() ); EXPECT_EQ( NOM_EXIT_SUCCESS, this->on_run() ); EXPECT_TRUE( this->compare() ); }