X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/07fff17b6aa083da20594aec02577f3e8ca296aa..57c6f0fe5f31e15e0cf7992f8eb654c82c1b7994:/src/propgrid/editors.cpp diff --git a/src/propgrid/editors.cpp b/src/propgrid/editors.cpp index a16baa76c4..fb60bdaa5f 100644 --- a/src/propgrid/editors.cpp +++ b/src/propgrid/editors.cpp @@ -4,7 +4,7 @@ // Author: Jaakko Salli // Modified by: // Created: 2007-04-14 -// RCS-ID: $Id: +// RCS-ID: $Id$ // Copyright: (c) Jaakko Salli // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// @@ -58,36 +58,33 @@ // This define is necessary to prevent macro clearing #define __wxPG_SOURCE_FILE__ -#include -#include -#include +#include "wx/propgrid/propgrid.h" +#include "wx/propgrid/editors.h" +#include "wx/propgrid/props.h" #if wxPG_USE_RENDERER_NATIVE - #include + #include "wx/renderer.h" #endif // How many pixels between textctrl and button #ifdef __WXMAC__ - #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 8 + #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 4 #else #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 2 #endif #define wxPG_BUTTON_SIZEDEC 0 -#include +#include "wx/odcombo.h" #ifdef __WXMSW__ - #include + #include "wx/msw/private.h" #endif // ----------------------------------------------------------------------- #if defined(__WXMSW__) // tested - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 1 #define wxPG_NAT_BUTTON_BORDER_X 1 #define wxPG_NAT_BUTTON_BORDER_Y 1 @@ -108,9 +105,6 @@ #define wxPG_CHECKMARK_HADJ (-1) #define wxPG_CHECKMARK_DEFLATE 3 - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 1 #define wxPG_NAT_BUTTON_BORDER_X 1 #define wxPG_NAT_BUTTON_BORDER_Y 1 @@ -125,14 +119,11 @@ #define wxPG_CHECKMARK_HADJ 0 #define wxPG_CHECKMARK_DEFLATE 0 - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 0 #define wxPG_NAT_BUTTON_BORDER_X 0 #define wxPG_NAT_BUTTON_BORDER_Y 0 - #define wxPG_TEXTCTRLYADJUST 3 + #define wxPG_TEXTCTRLYADJUST 0 #else // defaults @@ -142,9 +133,6 @@ #define wxPG_CHECKMARK_HADJ 0 #define wxPG_CHECKMARK_DEFLATE 0 - #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. - #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. - #define wxPG_NAT_BUTTON_BORDER_ANY 0 #define wxPG_NAT_BUTTON_BORDER_X 0 #define wxPG_NAT_BUTTON_BORDER_Y 0 @@ -153,16 +141,14 @@ #endif -#if (!wxPG_NAT_TEXTCTRL_BORDER_X && !wxPG_NAT_TEXTCTRL_BORDER_Y) - #define wxPG_ENABLE_CLIPPER_WINDOW 0 -#else - #define wxPG_ENABLE_CLIPPER_WINDOW 1 -#endif - - // for odcombo +#ifdef __WXMAC__ +#define wxPG_CHOICEXADJUST -3 // required because wxComboCtrl reserves 3pixels for wxTextCtrl's focus ring +#define wxPG_CHOICEYADJUST -3 +#else #define wxPG_CHOICEXADJUST 0 #define wxPG_CHOICEYADJUST 0 +#endif #define ODCB_CUST_PAINT_MARGIN 6 // Number added to image width for SetCustomPaintWidth @@ -181,6 +167,11 @@ wxPGEditor::~wxPGEditor() { } +wxString wxPGEditor::GetName() const +{ + return GetClassInfo()->GetClassName(); +} + void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const { if ( !property->IsValueUnspecified() ) @@ -224,200 +215,11 @@ bool wxPGEditor::CanContainCustomImage() const return false; } -// ----------------------------------------------------------------------- -// wxPGClipperWindow -// ----------------------------------------------------------------------- - - -#if wxPG_ENABLE_CLIPPER_WINDOW - -// -// Clipper window is used to "remove" borders from controls -// which otherwise insist on having them despite of supplied -// wxNO_BORDER window style. -// -class wxPGClipperWindow : public wxWindow -{ - DECLARE_CLASS(wxPGClipperWindow) -public: - - wxPGClipperWindow() - : wxWindow() - { - wxPGClipperWindow::Init(); - } - - wxPGClipperWindow(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize) - { - Init(); - Create(parent,id,pos,size); - } - - void Create(wxWindow* parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize); - - virtual ~wxPGClipperWindow(); - - virtual bool ProcessEvent(wxEvent& event); - - inline wxWindow* GetControl() const { return m_ctrl; } - - // This is called before wxControl is constructed. - void GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ); - - // This is caleed after wxControl has been constructed. - void SetControl( wxWindow* ctrl ); - - virtual void Refresh( bool eraseBackground = true, - const wxRect *rect = (const wxRect *) NULL ); - virtual void SetFocus(); - - virtual bool SetFont(const wxFont& font); - - inline int GetXClip() const { return m_xadj; } - - inline int GetYClip() const { return m_yadj; } - -protected: - wxWindow* m_ctrl; - - int m_xadj; // Horizontal border clip. - - int m_yadj; // Vertical border clip. - -private: - void Init () - { - m_ctrl = (wxWindow*) NULL; - } -}; - - -IMPLEMENT_CLASS(wxPGClipperWindow,wxWindow) - - -// This is called before wxControl is constructed. -void wxPGClipperWindow::GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ) -{ - m_xadj = xadj; - m_yadj = yadj; - pt.x = -xadj; - pt.y = -yadj; - wxSize own_size = GetSize(); - sz.x = own_size.x+(xadj*2); - sz.y = own_size.y+(yadj*2); -} - - -// This is caleed after wxControl has been constructed. -void wxPGClipperWindow::SetControl( wxWindow* ctrl ) -{ - m_ctrl = ctrl; - - // GTK requires this. - ctrl->SetSizeHints(3,3); - - // Correct size of this window to match the child. - wxSize sz = GetSize(); - wxSize chsz = ctrl->GetSize(); - - int hei_adj = chsz.y - (sz.y+(m_yadj*2)); - if ( hei_adj ) - SetSize(sz.x,chsz.y-(m_yadj*2)); - -} - - -void wxPGClipperWindow::Refresh( bool eraseBackground, const wxRect *rect ) -{ - wxWindow::Refresh(false,rect); - if ( m_ctrl ) - m_ctrl->Refresh(eraseBackground); -} - - -// Pass focus to control -void wxPGClipperWindow::SetFocus() -{ - if ( m_ctrl ) - m_ctrl->SetFocus(); - else - wxWindow::SetFocus(); -} - - -bool wxPGClipperWindow::SetFont(const wxFont& font) -{ - bool res = wxWindow::SetFont(font); - if ( m_ctrl ) - return m_ctrl->SetFont(font); - return res; -} - - -void wxPGClipperWindow::Create(wxWindow* parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size ) -{ - wxWindow::Create(parent,id,pos,size); -} - - -wxPGClipperWindow::~wxPGClipperWindow() -{ -} - - -bool wxPGClipperWindow::ProcessEvent(wxEvent& event) -{ - if ( event.GetEventType() == wxEVT_SIZE ) - { - if ( m_ctrl ) - { - // Maintain correct size relationship. - wxSize sz = GetSize(); - m_ctrl->SetSize(sz.x+(m_xadj*2),sz.y+(m_yadj*2)); - event.Skip(); - return false; - } - } - return wxWindow::ProcessEvent(event); -} - -#endif // wxPG_ENABLE_CLIPPER_WINDOW - -/*wxWindow* wxPropertyGrid::GetActualEditorControl( wxWindow* ctrl ) -{ -#if wxPG_ENABLE_CLIPPER_WINDOW - // Pass real control instead of clipper window - if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) - { - return ((wxPGClipperWindow*)ctrl)->GetControl(); - } -#else - return ctrl; -#endif -}*/ - // ----------------------------------------------------------------------- // wxPGTextCtrlEditor // ----------------------------------------------------------------------- -// Clipper window support macro (depending on whether it is used -// for this editor or not) -#if wxPG_NAT_TEXTCTRL_BORDER_X || wxPG_NAT_TEXTCTRL_BORDER_Y - #define wxPG_NAT_TEXTCTRL_BORDER_ANY 1 -#else - #define wxPG_NAT_TEXTCTRL_BORDER_ANY 0 -#endif - -WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor) wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, @@ -434,7 +236,8 @@ wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, return (wxWindow*) NULL; if ( !property->IsValueUnspecified() ) - text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY) ? + 0 : wxPG_EDITABLE_VALUE); int flags = 0; if ( (property->GetFlags() & wxPG_PROP_PASSWORD) && @@ -594,7 +397,7 @@ wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { } // ----------------------------------------------------------------------- -WX_PG_IMPLEMENT_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor) // This is a special enhanced double-click processor class. @@ -818,7 +621,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, else { if ( !p->IsValueUnspecified() ) - text = p->GetValueString(0); + text = p->GetValueAsString(0); } } @@ -877,7 +680,7 @@ void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, wxPoint pt(rect.x + wxPG_CONTROL_MARGIN - wxPG_CHOICEXADJUST - 1, rect.y + 1); - int renderFlags = 0; + int renderFlags = wxPGCellRenderer::DontUseCellColours; if ( flags & wxODCB_PAINTING_CONTROL ) renderFlags |= wxPGCellRenderer::Control; @@ -1017,7 +820,7 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, si.x -= wxPG_CHOICEXADJUST; wxWindow* ctrlParent = propGrid->GetPanel(); - int odcbFlags = extraStyle | wxNO_BORDER | wxTE_PROCESS_ENTER; + int odcbFlags = extraStyle | wxBORDER_NONE | wxTE_PROCESS_ENTER; // // If common value specified, use appropriate index @@ -1069,11 +872,11 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, // Connect event handling wxWindowID id = cb->GetId(); propGrid->Connect(id, wxEVT_COMMAND_COMBOBOX_SELECTED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); propGrid->Connect(id, wxEVT_COMMAND_TEXT_UPDATED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); propGrid->Connect(id, wxEVT_COMMAND_TEXT_ENTER, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); #ifdef __WXMSW__ cb->Show(); @@ -1210,13 +1013,15 @@ wxPGChoiceEditor::~wxPGChoiceEditor() { } // ----------------------------------------------------------------------- -WX_PG_IMPLEMENT_EDITOR_CLASS(ComboBox,wxPGComboBoxEditor,wxPGChoiceEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ComboBox, + wxPGComboBoxEditor, + wxPGChoiceEditor) void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - cb->SetValue(property->GetValueString(wxPG_EDITABLE_VALUE)); + cb->SetValue(property->GetValueAsString(wxPG_EDITABLE_VALUE)); // TODO: If string matches any selection, then select that. } @@ -1289,8 +1094,9 @@ wxPGComboBoxEditor::~wxPGComboBoxEditor() { } // ----------------------------------------------------------------------- -// This simpler implement_editor macro doesn't define class body. -WX_PG_IMPLEMENT_EDITOR_CLASS(ChoiceAndButton,wxPGChoiceAndButtonEditor,wxPGChoiceEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(ChoiceAndButton, + wxPGChoiceAndButtonEditor, + wxPGChoiceEditor) wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, @@ -1321,7 +1127,7 @@ wxPGWindowList wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGr ch_sz.x -= wxPG_TEXTCTRL_AND_BUTTON_SPACING; #endif - wxWindow* ch = wxPG_EDITOR(Choice)->CreateControls(propGrid,property, + wxWindow* ch = wxPGEditor_Choice->CreateControls(propGrid,property, pos,ch_sz).m_primary; #ifdef __WXMSW__ @@ -1339,9 +1145,9 @@ wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { } // wxPGTextCtrlAndButtonEditor // ----------------------------------------------------------------------- - -// This simpler implement_editor macro doesn't define class body. -WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrlAndButton,wxPGTextCtrlAndButtonEditor,wxPGTextCtrlEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(TextCtrlAndButton, + wxPGTextCtrlAndButtonEditor, + wxPGTextCtrlEditor) wxPGWindowList wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, @@ -1366,7 +1172,9 @@ wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { } #if wxPG_INCLUDE_CHECKBOX -WX_PG_IMPLEMENT_EDITOR_CLASS(CheckBox,wxPGCheckBoxEditor,wxPGEditor) +WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(CheckBox, + wxPGCheckBoxEditor, + wxPGEditor) // state argument: 0x01 = set if checked @@ -1432,7 +1240,7 @@ public: wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize ) - : wxControl(parent,id,pos,size,wxNO_BORDER|wxWANTS_CHARS) + : wxControl(parent,id,pos,size,wxBORDER_NONE|wxWANTS_CHARS) { // Due to SetOwnFont stuff necessary for GTK+ 1.2, we need to have this SetFont( parent->GetFont() ); @@ -1491,14 +1299,6 @@ bool wxSimpleCheckBox::ProcessEvent(wxEvent& event) wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent()->GetParent(); wxASSERT( propGrid->IsKindOf(CLASSINFO(wxPropertyGrid)) ); - if ( event.GetEventType() == wxEVT_NAVIGATION_KEY ) - { - //wxLogDebug(wxT("wxEVT_NAVIGATION_KEY")); - //SetFocusFromKbd(); - //event.Skip(); - //return wxControl::ProcessEvent(event); - } - else if ( ( (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK) && ((wxMouseEvent&)event).m_x > (wxPG_XBEFORETEXT-2) && ((wxMouseEvent&)event).m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight) ) @@ -1569,12 +1369,6 @@ bool wxSimpleCheckBox::ProcessEvent(wxEvent& event) { wxKeyEvent& keyEv = (wxKeyEvent&) event; - if ( keyEv.GetKeyCode() == WXK_TAB ) - { - propGrid->SendNavigationKeyEvent( keyEv.ShiftDown()?0:1 ); - return true; - } - else if ( keyEv.GetKeyCode() == WXK_SPACE ) { SetValue(2); @@ -1738,14 +1532,6 @@ wxWindow* wxPropertyGrid::GetEditorControl() const if ( !ctrl ) return ctrl; - // If it's clipper window, return its child instead -#if wxPG_ENABLE_CLIPPER_WINDOW - if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) - { - return ((wxPGClipperWindow*)ctrl)->GetControl(); - } -#endif - return ctrl; } @@ -1823,29 +1609,6 @@ void wxPropertyGrid::CorrectEditorWidgetPosY() // ----------------------------------------------------------------------- -bool wxPropertyGrid::AdjustPosForClipperWindow( wxWindow* topCtrlWnd, int* x, int* y ) -{ -#if wxPG_ENABLE_CLIPPER_WINDOW - // Take clipper window into account - if (topCtrlWnd->GetPosition().x < 1 && - !topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow))) - { - topCtrlWnd = topCtrlWnd->GetParent(); - wxASSERT( topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) ); - *x -= ((wxPGClipperWindow*)topCtrlWnd)->GetXClip(); - *y -= ((wxPGClipperWindow*)topCtrlWnd)->GetYClip(); - return true; - } -#else - wxUnusedVar(topCtrlWnd); - wxUnusedVar(x); - wxUnusedVar(y); -#endif - return false; -} - -// ----------------------------------------------------------------------- - // Fixes position of wxTextCtrl-like control (wxSpinCtrl usually // fits into that category as well). void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl, const wxPoint& offset ) @@ -1895,7 +1658,7 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, // Need to reduce width of text control on Mac #if defined(__WXMAC__) - s.x -= 8; + s.x -= 8; #endif // Take button into acccount @@ -1911,46 +1674,20 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, if ( (sz.y - m_lineHeight) > 5 ) hasSpecialSize = true; -#if wxPG_NAT_TEXTCTRL_BORDER_ANY - - // Create clipper window - wxPGClipperWindow* wnd = new wxPGClipperWindow(); -#if defined(__WXMSW__) - wnd->Hide(); -#endif - wnd->Create(GetPanel(),id,p,s); - - // This generates rect of the control inside the clipper window - if ( !hasSpecialSize ) - wnd->GetControlRect(wxPG_NAT_TEXTCTRL_BORDER_X, wxPG_NAT_TEXTCTRL_BORDER_Y, p, s); - else - wnd->GetControlRect(0, 0, p, s); - - wxWindow* ctrlParent = wnd; - -#else - wxWindow* ctrlParent = GetPanel(); if ( !hasSpecialSize ) - tcFlags |= wxNO_BORDER; - -#endif + tcFlags |= wxBORDER_NONE; wxTextCtrl* tc = new wxTextCtrl(); -#if defined(__WXMSW__) && !wxPG_NAT_TEXTCTRL_BORDER_ANY +#if defined(__WXMSW__) tc->Hide(); #endif SetupTextCtrlValue(value); tc->Create(ctrlParent,id,value, p, s,tcFlags); - -#if wxPG_NAT_TEXTCTRL_BORDER_ANY - wxWindow* ed = wnd; - wnd->SetControl(tc); -#else + wxWindow* ed = tc; -#endif // Center the control vertically if ( !hasSpecialSize ) @@ -1969,9 +1706,9 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, // Connect event handling id = ed->GetId(); this->Connect(id, wxEVT_COMMAND_TEXT_UPDATED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); this->Connect(id, wxEVT_COMMAND_TEXT_ENTER, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); return (wxWindow*) ed; } @@ -2037,7 +1774,7 @@ wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize // Connect event handling id = but->GetId(); this->Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); return but; } @@ -2065,7 +1802,7 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos, wxString text; if ( !property->IsValueUnspecified() ) - text = property->GetValueString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); return GenerateEditorTextCtrl(pos,sz,text,but,property->m_maxLen); } @@ -2141,11 +1878,11 @@ void wxPGMultiButton::Finalize( wxPropertyGrid* propGrid, const wxPoint& pos ) Move( pos.x + m_fullEditorSize.x - m_buttonsWidth, pos.y ); // Connect event handling - for ( int i=0; iConnect(id, wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent)); + wxEventHandler(wxPropertyGrid::OnCustomEditorEvent)); } }