SI_Error SMDNode::Write( FILE *l_fptr ) { fprintf ( l_fptr, "%d %c%s%c %d\n",GetID(), 34, GetName(), 34, GetParentID() ); return SI_SUCCESS; }
void CGUIToggleButtonControl::SetToggleSelect(const std::string &toggleSelect) { m_toggleSelect = g_infoManager.Register(toggleSelect, GetParentID()); }
EVENT_RESULT CGUISliderControl::OnMouseEvent(const CPoint &point, const CMouseEvent &event) { m_dragging = false; if (event.m_id == ACTION_MOUSE_DRAG) { m_dragging = true; bool guessSelector = false; if (event.m_state == 1) { // grab exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); SendWindowMessage(msg); guessSelector = true; } else if (event.m_state == 3) { // release exclusive access m_dragging = false; CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); SendWindowMessage(msg); } SetFromPosition(point, guessSelector); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_LEFT_CLICK && m_guiBackground.HitTest(point)) { SetFromPosition(point, true); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_WHEEL_UP) { if (m_guiBackground.HitTest(point)) { Move(10); return EVENT_RESULT_HANDLED; } } else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN) { if (m_guiBackground.HitTest(point)) { Move(-10); return EVENT_RESULT_HANDLED; } } else if (event.m_id == ACTION_GESTURE_NOTIFY) { return EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA; } else if (event.m_id == ACTION_GESTURE_BEGIN) { // grab exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); SendWindowMessage(msg); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_PAN) { // do the drag SetFromPosition(point); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_END) { // release exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); SendWindowMessage(msg); return EVENT_RESULT_HANDLED; } return EVENT_RESULT_UNHANDLED; }
void CGUIBaseContainer::SetAutoScrolling(const TiXmlNode *node) { if (!node) return; const TiXmlElement *scroll = node->FirstChildElement("autoscroll"); if (scroll) { scroll->Attribute("time", &m_autoScrollMoveTime); if (scroll->Attribute("reverse")) m_autoScrollIsReversed = true; if (scroll->FirstChild()) m_autoScrollCondition = g_infoManager.Register(scroll->FirstChild()->ValueStr(), GetParentID()); } }
void CGUIRadioButtonControl::SetToggleSelect(const CStdString &toggleSelect) { m_toggleSelect = g_infoManager.Register(toggleSelect, GetParentID()); }
void CGUISelectButtonControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { if (m_bInvalidated) { m_imgBackground.SetWidth(m_width); m_imgBackground.SetHeight(m_height); } // Are we in selection mode if (m_bShowSelect) { // render background, left and right arrow if (m_imgBackground.Process(currentTime)) MarkDirtyRegion(); CGUILabel::COLOR color = CGUILabel::COLOR_TEXT; // User has moved left... if (m_bMovedLeft) { m_iStartFrame++; if (m_iStartFrame >= 10) { m_iStartFrame = 0; m_bMovedLeft = false; MarkDirtyRegion(); } // If we are moving left // render item text as disabled color = CGUILabel::COLOR_DISABLED; } // Update arrow m_imgLeftFocus.Process(currentTime); m_imgLeft.Process(currentTime); // User has moved right... if (m_bMovedRight) { m_iStartFrame++; if (m_iStartFrame >= 10) { m_iStartFrame = 0; m_bMovedRight = false; MarkDirtyRegion(); } // If we are moving right // render item text as disabled color = CGUILabel::COLOR_DISABLED; } // Update arrow m_imgRightFocus.Process(currentTime); m_imgRight.Process(currentTime); // Render text if a current item is available if (m_iCurrentItem >= 0 && (unsigned)m_iCurrentItem < m_vecItems.size()) { bool changed = m_label.SetMaxRect(m_posX, m_posY, m_width, m_height); changed |= m_label.SetText(m_vecItems[m_iCurrentItem]); changed |= m_label.SetColor(color); changed |= m_label.Process(currentTime); if (changed) MarkDirtyRegion(); } // Select current item, if user doesn't // move left or right for 1.5 sec. unsigned int ticksSpan = currentTime - m_ticks; if (ticksSpan > 1500) { // User hasn't moved disable selection mode... m_bShowSelect = false; MarkDirtyRegion(); // ...and send a thread message. // (Sending a message with SendMessage // can result in a GPF.) CGUIMessage message(GUI_MSG_CLICKED, GetID(), GetParentID() ); g_windowManager.SendThreadMessage(message); } CGUIControl::Process(currentTime, dirtyregions); } // if (m_bShowSelect) else CGUIButtonControl::Process(currentTime, dirtyregions); }
void CGUIFadeLabelControl::AddLabel(const std::string &label) { m_infoLabels.push_back(CGUIInfoLabel(label, "", GetParentID())); }
bool IsTopID(word id) { word pid=GetParentID(id); return pid==id; }
EVENT_RESULT CGUIBaseContainer::OnMouseEvent(const CPoint &point, const CMouseEvent &event) { if (event.m_id == ACTION_MOUSE_LEFT_CLICK || event.m_id == ACTION_MOUSE_DOUBLE_CLICK || event.m_id == ACTION_MOUSE_RIGHT_CLICK) { if (SelectItemFromPoint(point - CPoint(m_posX, m_posY))) { OnClick(event.m_id); return EVENT_RESULT_HANDLED; } } else if (event.m_id == ACTION_MOUSE_WHEEL_UP) { Scroll(-1); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN) { Scroll(1); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_NOTIFY) { return (m_orientation == HORIZONTAL) ? EVENT_RESULT_PAN_HORIZONTAL : EVENT_RESULT_PAN_VERTICAL; } else if (event.m_id == ACTION_GESTURE_BEGIN) { // grab exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); SendWindowMessage(msg); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_PAN) { // do the drag and validate our offset (corrects for end of scroll) m_scroller.SetValue(m_scroller.GetValue() - ((m_orientation == HORIZONTAL) ? event.m_offsetX : event.m_offsetY)); float size = (m_layout) ? m_layout->Size(m_orientation) : 10.0f; int offset = (int)MathUtils::round_int(m_scroller.GetValue() / size); m_lastScrollStartTimer.Stop(); m_scrollTimer.Start(); SetOffset(offset); ValidateOffset(); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_END) { // release exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); SendWindowMessage(msg); m_scrollTimer.Stop(); // and compute the nearest offset from this and scroll there float size = (m_layout) ? m_layout->Size(m_orientation) : 10.0f; float offset = m_scroller.GetValue() / size; int toOffset = (int)MathUtils::round_int(offset); if (toOffset < offset) SetOffset(toOffset+1); else SetOffset(toOffset-1); ScrollToOffset(toOffset); return EVENT_RESULT_HANDLED; } return EVENT_RESULT_UNHANDLED; }
void CGUIEditControl::ProcessText(unsigned int currentTime) { if (m_smsTimer.IsRunning() && m_smsTimer.GetElapsedMilliseconds() > smsDelay) UpdateText(); if (m_bInvalidated) { m_label.SetMaxRect(m_posX, m_posY, m_width, m_height); m_label.SetText(m_info.GetLabel(GetParentID())); RecalcLabelPosition(); } bool changed = false; m_clipRect.x1 = m_label.GetRenderRect().x1; m_clipRect.x2 = m_clipRect.x1 + m_label.GetMaxWidth(); m_clipRect.y1 = m_posY; m_clipRect.y2 = m_posY + m_height; // start by rendering the normal text float leftTextWidth = m_label.GetRenderRect().Width(); if (leftTextWidth > 0) { // render the text on the left changed |= m_label.SetColor(GetTextColor()); changed |= m_label.Process(currentTime); m_clipRect.x1 += leftTextWidth + spaceWidth; } if (g_graphicsContext.SetClipRegion(m_clipRect.x1, m_clipRect.y1, m_clipRect.Width(), m_clipRect.Height())) { uint32_t align = m_label.GetLabelInfo().align & XBFONT_CENTER_Y; // start aligned left if (m_label2.GetTextWidth() < m_clipRect.Width()) { // align text as our text fits if (leftTextWidth > 0) { // right align as we have 2 labels align |= XBFONT_RIGHT; } else { // align by whatever the skinner requests align |= (m_label2.GetLabelInfo().align & 3); } } changed |= m_label2.SetMaxRect(m_clipRect.x1 + m_textOffset, m_posY, m_clipRect.Width() - m_textOffset, m_height); std::wstring text = GetDisplayedText(); std::string hint = m_hintInfo.GetLabel(GetParentID()); if (!HasFocus() && text.empty() && !hint.empty()) { changed |= m_label2.SetText(hint); } else if ((HasFocus() || GetParentID() == WINDOW_DIALOG_KEYBOARD) && m_inputType != INPUT_TYPE_READONLY) { changed |= SetStyledText(text); } else changed |= m_label2.SetTextW(text); changed |= m_label2.SetAlign(align); changed |= m_label2.SetColor(GetTextColor()); changed |= m_label2.SetOverflow(CGUILabel::OVER_FLOW_CLIP); changed |= m_label2.Process(currentTime); g_graphicsContext.RestoreClipRegion(); } if (changed) MarkDirtyRegion(); }
void CGUIControlGroupList::Render() { if (m_scrollSpeed != 0) { m_offset += m_scrollSpeed * (m_renderTime - m_scrollTime); if (m_scrollSpeed < 0 && m_offset < m_scrollOffset || m_scrollSpeed > 0 && m_offset > m_scrollOffset) { m_offset = m_scrollOffset; m_scrollSpeed = 0; } } m_scrollTime = m_renderTime; ValidateOffset(); if (m_pageControl) { CGUIMessage message(GUI_MSG_LABEL_RESET, GetParentID(), m_pageControl, (DWORD)m_height, (DWORD)m_totalSize); SendWindowMessage(message); CGUIMessage message2(GUI_MSG_ITEM_SELECT, GetParentID(), m_pageControl, (DWORD)m_offset); SendWindowMessage(message2); } // we run through the controls, rendering as we go bool render(g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)); float pos = 0; float focusedPos = 0; CGUIControl *focusedControl = NULL; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { // note we render all controls, even if they're offscreen, as then they'll be updated // with respect to animations CGUIControl *control = *it; control->UpdateVisibility(); if (m_renderFocusedLast && control->HasFocus()) { focusedControl = control; focusedPos = pos; } else { if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + pos - m_offset); else g_graphicsContext.SetOrigin(m_posX + pos - m_offset, m_posY); control->DoRender(m_renderTime); } if (control->IsVisible()) pos += Size(control) + m_itemGap; g_graphicsContext.RestoreOrigin(); } if (focusedControl) { if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + focusedPos - m_offset); else g_graphicsContext.SetOrigin(m_posX + focusedPos - m_offset, m_posY); focusedControl->DoRender(m_renderTime); } if (render) g_graphicsContext.RestoreClipRegion(); CGUIControl::Render(); }
void CGUIEditControl::OnClick() { // we received a click - it's not from the keyboard, so pop up the virtual keyboard, unless // that is where we reside! if (GetParentID() == WINDOW_DIALOG_KEYBOARD) return; std::string utf8; g_charsetConverter.wToUTF8(m_text2, utf8); bool textChanged = false; switch (m_inputType) { case INPUT_TYPE_READONLY: textChanged = false; break; case INPUT_TYPE_NUMBER: textChanged = CGUIDialogNumeric::ShowAndGetNumber(utf8, m_inputHeading); break; case INPUT_TYPE_SECONDS: textChanged = CGUIDialogNumeric::ShowAndGetSeconds(utf8, g_localizeStrings.Get(21420)); break; case INPUT_TYPE_TIME: { CDateTime dateTime; dateTime.SetFromDBTime(utf8); SYSTEMTIME time; dateTime.GetAsSystemTime(time); if (CGUIDialogNumeric::ShowAndGetTime(time, !m_inputHeading.empty() ? m_inputHeading : g_localizeStrings.Get(21420))) { dateTime = CDateTime(time); utf8 = dateTime.GetAsLocalizedTime("", false); textChanged = true; } break; } case INPUT_TYPE_DATE: { CDateTime dateTime; dateTime.SetFromDBDate(utf8); if (dateTime < CDateTime(2000,1, 1, 0, 0, 0)) dateTime = CDateTime(2000, 1, 1, 0, 0, 0); SYSTEMTIME date; dateTime.GetAsSystemTime(date); if (CGUIDialogNumeric::ShowAndGetDate(date, !m_inputHeading.empty() ? m_inputHeading : g_localizeStrings.Get(21420))) { dateTime = CDateTime(date); utf8 = dateTime.GetAsDBDate(); textChanged = true; } break; } case INPUT_TYPE_IPADDRESS: textChanged = CGUIDialogNumeric::ShowAndGetIPAddress(utf8, m_inputHeading); break; case INPUT_TYPE_SEARCH: textChanged = CGUIKeyboardFactory::ShowAndGetFilter(utf8, true); break; case INPUT_TYPE_FILTER: textChanged = CGUIKeyboardFactory::ShowAndGetFilter(utf8, false); break; case INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW: textChanged = CGUIDialogNumeric::ShowAndVerifyNewPassword(utf8); break; case INPUT_TYPE_PASSWORD_MD5: utf8 = ""; // TODO: Ideally we'd send this to the keyboard and tell the keyboard we have this type of input // fallthrough case INPUT_TYPE_TEXT: default: textChanged = CGUIKeyboardFactory::ShowAndGetInput(utf8, m_inputHeading, true, m_inputType == INPUT_TYPE_PASSWORD || m_inputType == INPUT_TYPE_PASSWORD_MD5); break; } if (textChanged) { ClearMD5(); m_edit.clear(); g_charsetConverter.utf8ToW(utf8, m_text2); m_cursorPos = m_text2.size(); UpdateText(); m_cursorPos = m_text2.size(); } }
bool CGUIEditControl::OnAction(const CAction &action) { ValidateCursor(); if (m_inputType != INPUT_TYPE_READONLY) { if (action.GetID() == ACTION_BACKSPACE) { // backspace if (m_cursorPos) { if (!ClearMD5()) m_text2.erase(--m_cursorPos, 1); UpdateText(); } return true; } else if (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_CURSOR_LEFT) { if (m_cursorPos > 0) { m_cursorPos--; UpdateText(false); return true; } } else if (action.GetID() == ACTION_MOVE_RIGHT || action.GetID() == ACTION_CURSOR_RIGHT) { if ((unsigned int) m_cursorPos < m_text2.size()) { m_cursorPos++; UpdateText(false); return true; } } else if (action.GetID() == ACTION_PASTE) { ClearMD5(); OnPasteClipboard(); return true; } else if (action.GetID() >= KEY_VKEY && action.GetID() < KEY_ASCII && m_edit.empty()) { // input from the keyboard (vkey, not ascii) BYTE b = action.GetID() & 0xFF; if (b == XBMCVK_HOME) { m_cursorPos = 0; UpdateText(false); return true; } else if (b == XBMCVK_END) { m_cursorPos = m_text2.length(); UpdateText(false); return true; } if (b == XBMCVK_LEFT && m_cursorPos > 0) { m_cursorPos--; UpdateText(false); return true; } if (b == XBMCVK_RIGHT && m_cursorPos < m_text2.length()) { m_cursorPos++; UpdateText(false); return true; } if (b == XBMCVK_DELETE) { if (m_cursorPos < m_text2.length()) { if (!ClearMD5()) m_text2.erase(m_cursorPos, 1); UpdateText(); return true; } } if (b == XBMCVK_BACK) { if (m_cursorPos > 0) { if (!ClearMD5()) m_text2.erase(--m_cursorPos, 1); UpdateText(); } return true; } else if (b == XBMCVK_RETURN || b == XBMCVK_NUMPADENTER) { // enter - send click message, but otherwise ignore SEND_CLICK_MESSAGE(GetID(), GetParentID(), 1); return true; } else if (b == XBMCVK_ESCAPE) { // escape - fallthrough to default action return CGUIButtonControl::OnAction(action); } } else if (action.GetID() >= KEY_ASCII) { // input from the keyboard int ch = action.GetUnicode(); // ignore non-printing characters if ( !((0 <= ch && ch < 0x8) || (0xE <= ch && ch < 0x1B) || (0x1C <= ch && ch < 0x20)) ) { switch (ch) { case 9: // tab, ignore case 11: // Non-printing character, ignore case 12: // Non-printing character, ignore break; case 10: case 13: { // enter - send click message, but otherwise ignore SEND_CLICK_MESSAGE(GetID(), GetParentID(), 1); return true; } case 27: { // escape - fallthrough to default action return CGUIButtonControl::OnAction(action); } case 8: { // backspace if (m_cursorPos) { if (!ClearMD5()) m_text2.erase(--m_cursorPos, 1); } break; } case 127: { // delete if (m_cursorPos < m_text2.length()) { if (!ClearMD5()) m_text2.erase(m_cursorPos, 1); } break; } default: { if (!g_Windowing.IsTextInputEnabled()) { ClearMD5(); m_edit.clear(); m_text2.insert(m_text2.begin() + m_cursorPos++, (WCHAR)action.GetUnicode()); } break; } } UpdateText(); return true; } } else if (action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) { // input from the remote ClearMD5(); m_edit.clear(); OnSMSCharacter(action.GetID() - REMOTE_0); return true; } else if (action.GetID() == ACTION_INPUT_TEXT) { m_edit.clear(); std::wstring str; g_charsetConverter.utf8ToW(action.GetText(), str); m_text2.insert(m_cursorPos, str); m_cursorPos += str.size(); UpdateText(); return true; } } return CGUIButtonControl::OnAction(action); }
void CGUITextBox::SetAutoScrolling(const TiXmlNode *node) { if (!node) return; const TiXmlElement *scroll = node->FirstChildElement("autoscroll"); if (scroll) { scroll->Attribute("delay", &m_autoScrollDelay); scroll->Attribute("time", &m_autoScrollTime); if (scroll->FirstChild()) m_autoScrollCondition = g_infoManager.Register(scroll->FirstChild()->ValueStr(), GetParentID()); int repeatTime; if (scroll->Attribute("repeat", &repeatTime)) m_autoScrollRepeatAnim = new CAnimation(CAnimation::CreateFader(100, 0, repeatTime, 1000)); } }
bool CGUISpinControl::OnAction(const CAction &action) { switch (action.GetID()) { case REMOTE_0: case REMOTE_1: case REMOTE_2: case REMOTE_3: case REMOTE_4: case REMOTE_5: case REMOTE_6: case REMOTE_7: case REMOTE_8: case REMOTE_9: { if (strlen(m_szTyped) >= 3) { m_iTypedPos = 0; strcpy(m_szTyped, ""); } int iNumber = action.GetID() - REMOTE_0; m_szTyped[m_iTypedPos] = iNumber + '0'; m_iTypedPos++; m_szTyped[m_iTypedPos] = 0; int iValue; sscanf(m_szTyped, "%i", &iValue); switch (m_iType) { case SPIN_CONTROL_TYPE_INT: { if (iValue < m_iStart || iValue > m_iEnd) { m_iTypedPos = 0; m_szTyped[m_iTypedPos] = iNumber + '0'; m_iTypedPos++; m_szTyped[m_iTypedPos] = 0; sscanf(m_szTyped, "%i", &iValue); if (iValue < m_iStart || iValue > m_iEnd) { m_iTypedPos = 0; strcpy(m_szTyped, ""); return true; } } m_iValue = iValue; CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); SendWindowMessage(msg); } break; case SPIN_CONTROL_TYPE_TEXT: { if (iValue < 0 || iValue >= (int)m_vecLabels.size()) { m_iTypedPos = 0; m_szTyped[m_iTypedPos] = iNumber + '0'; m_iTypedPos++; m_szTyped[m_iTypedPos] = 0; sscanf(m_szTyped, "%i", &iValue); if (iValue < 0 || iValue >= (int)m_vecLabels.size()) { m_iTypedPos = 0; strcpy(m_szTyped, ""); return true; } } m_iValue = iValue; CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID()); SendWindowMessage(msg); } break; } return true; } break; case ACTION_PAGE_UP: if (!m_bReverse) PageDown(); else PageUp(); return true; break; case ACTION_PAGE_DOWN: if (!m_bReverse) PageUp(); else PageDown(); return true; break; case ACTION_SELECT_ITEM: if (m_iSelect == SPIN_BUTTON_UP) { MoveUp(); return true; } if (m_iSelect == SPIN_BUTTON_DOWN) { MoveDown(); return true; } break; } /* static float m_fSmoothScrollOffset = 0.0f; if (action.GetID() == ACTION_SCROLL_UP) { m_fSmoothScrollOffset += action.GetAmount() * action.GetAmount(); bool handled = false; while (m_fSmoothScrollOffset > 0.4) { handled = true; m_fSmoothScrollOffset -= 0.4f; MoveDown(); } return handled; }*/ return CGUIControl::OnAction(action); }
void Scale::SetScale(const float x, const float y, const float z) { CalculateScaleMatrix(x, y, z); GameObject::GetComponent<Transformation>(GetParentID()).SetChanged(); }
bool CGUIControl::OnMessage(CGUIMessage& message) { if ( message.GetControlId() == GetID() ) { switch (message.GetMessage() ) { case GUI_MSG_SETFOCUS: // if control is disabled then move 2 the next control if ( !CanFocus() ) { CLog::Log(LOGERROR, "Control %u in window %u has been asked to focus, " "but it can't", GetID(), GetParentID()); return false; } SetFocus(true); { // inform our parent window that this has happened CGUIMessage message(GUI_MSG_FOCUSED, GetParentID(), GetID()); if (m_parentControl) m_parentControl->OnMessage(message); } return true; break; case GUI_MSG_LOSTFOCUS: { SetFocus(false); // and tell our parent so it can unfocus if (m_parentControl) m_parentControl->OnMessage(message); return true; } break; case GUI_MSG_VISIBLE: SetVisible(true, true); return true; break; case GUI_MSG_HIDDEN: SetVisible(false); return true; // Note that the skin <enable> tag will override these messages case GUI_MSG_ENABLED: SetEnabled(true); return true; case GUI_MSG_DISABLED: SetEnabled(false); return true; case GUI_MSG_WINDOW_RESIZE: // invalidate controls to get them to recalculate sizing information SetInvalid(); return true; } } return false; }
bool CGUIResizeControl::OnMouseClick(DWORD dwButton, const CPoint &point) { if (dwButton != MOUSE_LEFT_BUTTON) return false; g_Mouse.EndExclusiveAccess(GetID(), GetParentID()); return true; }
void CGUIButtonControl::OnUnFocus() { m_unfocusActions.ExecuteActions(GetID(), GetParentID()); }
SpaceAddress CSpace::GetAddress(){ assert(IsValid()); return SpaceAddress(GetParentID(),GetSpaceID()); };