wxWidgets/C++ Tabbed Text Editor Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 6:28 pm

You would have to use a wxImageList for that.

Add a destructor to MyFrame.h:

Code: Select all

class MyFrame : public wxFrame {
public:
    MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
            const wxPoint& pos, const wxSize& size, const long type);
    virtual ~MyFrame(); // Destructor
and a wxImageList pointer member:

Code: Select all

private:
    wxImageList* m_imageList; // Image list
    //This class handles events
    DECLARE_EVENT_TABLE()
};
In MyFrame constructor (MyFrame::MyFrame) create and initialize m_imageList:

Code: Select all

    Notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(640,480), wxNB_LEFT);
    //m_text = new wxTextCtrl( Notebook, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );

    // Create new imagelist which takes images of 16x16 pixels
    m_imageList = new wxImageList(16, 16);
    m_imageList->Add(wxBitmap(child_xpm)); // Add image 0

    // Set it as the notebook's imagelist
    Notebook->SetImageList(m_imageList);
and add the destructor which frees m_imageList:

Code: Select all

/* MyFrame destructor */
MyFrame::~MyFrame() {
    // Have to delete the wxImageList
    delete m_imageList;
}
Modify MyFrame::OnNew() once more:

Code: Select all

void MyFrame::OnNew(wxCommandEvent& event){
    wxTextCtrl* text = new wxTextCtrl(Notebook,
        wxID_ANY,           // ID
        _T(""),             // Initial text
        wxDefaultPosition,  // Position
        wxDefaultSize,      // Size
        wxTE_MULTILINE);    // Flags
    Notebook->AddPage(text,
        wxString::Format(_T("Untitled %d"), gs_nFrames++), // Title
        true, // Select the tab (true/false)
        0); // Image index in image list we assigned with SetImageList() before
}
You should use another image since child_xpm is too big for the tab. Maybe 8x8 would be OK. If you change the size you would have to modify the wxImageList accordingly (16,16 -> 8,8).

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 6:32 pm

Thanks for the help :)
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 7:17 pm

More errors (*sigh*)
CWebGUIMain.cpp: In constructor 'MyFrame::MyFrame(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, long int)':
CWebGUIMain.cpp:146: error: invalid use of incomplete type 'struct wxImageList'
/usr/local/include/wx-2.8/wx/generic/listctrl.h:16: error: forward declaration of 'struct wxImageList'
CWebGUIMain.cpp:147: error: invalid use of member (did you forget the '&' ?)
CWebGUIMain.cpp:147: error: base operand of '->' is not a pointer
CWebGUIMain.cpp:150: error: no matching function for call to 'wxNotebook::SetImageList(<unresolved overloaded function type>)'
/usr/local/include/wx-2.8/wx/bookctrl.h:122: note: candidates are: virtual void wxBookCtrlBase::SetImageList(wxImageList*)
CWebGUIMain.cpp: In destructor 'virtual MyFrame::~MyFrame()':
CWebGUIMain.cpp:194: error: type '<unresolved overloaded function type>' argument given to 'delete', expected pointer
make[1]: *** [build/Linux_Debug/GNU-Linux-x86/CWebGUIMain.o] Error 1
make[1]: Leaving directory `/media/1GB/C++/CWebGUI'
make: *** [.build-impl] Error 2
Header file:

Code: Select all

/////////////////////////////////////////////////////////////////////////////
// Name:        CWebGUI.h
// Purpose:     Text Editor for web development
// Author:      Timothy J. Warren
// Created:     2008-02
// Copyright:   (c) 2008 Timothy J. Warren
// Licence:     Source on request
/////////////////////////////////////////////////////////////////////////////


#include "wx/wxprec.h"


#ifndef WX_PRECOMP
    #include "wx/wx.h"
    #include "wx/notebook.h"
    
    //#include "wx/print.h"
    //#include "wx/printdlg.h"
#endif

/*
#if wxUSE_FILESYSTEM
    #include "wx/filesys.h"
    #include "wx/fs_mem.h"
#endif
*/
#ifdef __WXMSW__
    #define USE_WXMSW 1
#else
    #define USE_WXMSW 0
#endif

#ifdef __WXUNIVERSAL__
    #define USE_WXUNIVERSAL 1
#else
    #define USE_WXUNIVERSAL 0
#endif

#ifdef __WXMAC__
    #define USE_WXMAC 1
#else
    #define USE_WXMAC 0
#endif

#ifdef __WXGTK__
    #define USE_WXGTK 1
#else
    #define USE_WXGTK 0
#endif

#ifdef __WXMOTIF__
    #define USE_WXMOTIF 1
#else
    #define USE_WXMOTIF 0
#endif

//Image files

#include "app.xpm"
#include "bitmaps/new.xpm"
#include "bitmaps/open.xpm"
#include "bitmaps/close.xpm"
#include "bitmaps/save.xpm"
#include "bitmaps/copy.xpm"
#include "bitmaps/cut.xpm"
#include "bitmaps/paste.xpm"
#include "bitmaps/print.xpm"
#include "bitmaps/help.xpm"


//Declare the application class
class MyApp : public wxApp{
public:
     virtual bool OnInit();

};

DECLARE_APP(MyApp)

//Declare our main frame class
//class MyCanvas;
class MyFrame : public wxFrame {
public:
    MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
            const wxPoint& pos, const wxSize& size, const long type);
    virtual ~MyFrame(); // Destructor 
    wxNotebook* Notebook;
    wxTextCtrl* m_text;
    void InitToolBar(wxToolBar* toolBar);
   
    /*-----Event handlers-----*/
    //File Menu
    void OnNew (wxCommandEvent& event);
    void OnOpen(wxCommandEvent& event);
    void OnSave(wxCommandEvent& event);
    void OnQuit (wxCommandEvent& event);

    //Help Menu
    void OnAbout (wxCommandEvent& event);
   
private:
    wxImageList* m_imageList(int width, int height); // Image list 
    //This class handles events
    DECLARE_EVENT_TABLE()
};


//Event table for MyFrame
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    //File Menu
    EVT_MENU(wxID_NEW, MyFrame::OnNew)
    EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
    EVT_MENU(wxID_SAVE, MyFrame::OnSave)
     /*
    #if wxUSE_CLIPBOARD
        EVT_MENU(wxID_COPY, MyChild::OnCopy)
        EVT_MENU(wxID_CUT, MyChild::OnCut)
        EVT_MENU(wxID_PASTE, MyChild::OnPaste)
    #endif //Use Clipboard
    EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs)
    EVT_MENU(ID_PRINT, MyFrame::OnPrint)
    EVT_MENU(ID_PREVIEW, MyFrame::OnPreview)
    EVT_MENU(ID_PAGE_SETUP, MyFrame::OnPageSetup)*/
    EVT_MENU(wxID_EXIT,  MyFrame::OnQuit)
    //Help Menu
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
END_EVENT_TABLE()
       
/*
enum{

    ID_PRINT,
    ID_PREVIEW,
    ID_PAGE_SETUP


};
   */     
 

Code: Select all

/////////////////////////////////////////////////////////////////////////////
// Name:        CWebGUI.cpp
// Purpose:     Text Editor for web development
// Author:      Timothy J. Warren
// Created:     2008-02
// Copyright:   (c) 2008 Timothy J. Warren
// Licence:     Source on request
/////////////////////////////////////////////////////////////////////////////


#include "CWebGUI.h" //For Includes and Classes

static int gs_nFrames = 0;

IMPLEMENT_APP(MyApp);

//Initialize the application
bool MyApp::OnInit(){
    MyFrame *frame = new MyFrame (NULL, wxID_ANY, _T("CWebGUI"), wxPoint(0,0),
                wxSize(640,480), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE);
    #ifndef __WXMAC__
        frame->Show(true);
    #endif
    //Start the event loop
    return true;
}

/*-------My Frame Event Functions-------*/
void MyFrame:: OnQuit(wxCommandEvent& WXUNUSED(event)){
    //Destroy the frame
    Close();
}

#if wxUSE_TOOLBAR
    void MyFrame::InitToolBar(wxToolBar* toolBar){
        wxBitmap bitmaps[8];

        bitmaps[0] = wxBitmap( new_xpm );
        bitmaps[1] = wxBitmap( open_xpm );
        bitmaps[2] = wxBitmap( save_xpm );
        bitmaps[3] = wxBitmap( copy_xpm );
        bitmaps[4] = wxBitmap( cut_xpm );
        bitmaps[5] = wxBitmap( paste_xpm );
        bitmaps[6] = wxBitmap( print_xpm );
        bitmaps[7] = wxBitmap( help_xpm );

        toolBar->AddTool(wxID_NEW, _T("New"), bitmaps[0], _T("New file"));
        toolBar->AddTool(wxID_OPEN, _T("Open"), bitmaps[1], _T("Open file"));
        toolBar->AddTool(wxID_SAVE, _T("Save"), bitmaps[2], _T("Save file"));

        #if wxUSE_CLIPBOARD
            toolBar->AddSeparator();
            toolBar->AddTool(wxID_COPY, _T("Copy"), bitmaps[3], _T("Copy"));
            toolBar->AddTool(wxID_CUT, _T("Cut"), bitmaps[4], _T("Cut"));
            toolBar->AddTool(wxID_PASTE, _T("Paste"), bitmaps[5], _T("Paste"));
            toolBar->AddSeparator();
        #endif //wxUSE_CLIPBOARD

        //toolBar->AddTool(wxID_PRINT, _T("Print"), bitmaps[6], _T("Print"));
        //toolBar->AddSeparator();
        toolBar->AddTool(wxID_ABOUT, _T("About"), bitmaps[7], _T("Help"));

        toolBar->Realize();
    }
#endif // wxUSE_TOOLBAR

//Help menu
void MyFrame:: OnAbout(wxCommandEvent& WXUNUSED(event)){
    wxString msg; //Dialog Message string
    msg.Printf(
    wxT("CWebGUI, a text editor for web development\n Version 1.0.0b\n Copyright 2008, Timothy J. Warren\n Special thanks to the wxWidgets Community"));
    wxMessageBox(msg, wxT("About CWebGUI"), //wxT("Title")
            wxOK | wxICON_INFORMATION, this);
}

/*-----End My Frame Event Functions-----*/


MyFrame::MyFrame(wxWindow *parent,const wxWindowID id, const wxString& title,
const wxPoint& pos, const wxSize& size, long style):
wxFrame(parent, id, title, pos, size, style){
    //Set the frame icon
    SetIcon(wxICON(app));

    //File Menu
    wxMenu *fileMenu = new wxMenu;
    fileMenu->Append(wxID_NEW, wxT("&New\tCtrl+N"),wxT("Create a new file"));
    fileMenu->AppendSeparator();
    fileMenu->Append(wxID_OPEN, wxT("&Open\tCtrl+O"),wxT("Open a file"));
    //fileMenu->Append(wxID_CLOSE, wxT("&Close\tCtrl+W"),wxT("Close current file"));
    fileMenu->Append(wxID_SAVE, wxT("&Save\tCtrl+S"),wxT("Save current file"));
    //fileMenu->Append(wxID_SAVEAS, wxT("Save &As...\tShift+Ctrl+S"),wxT("Save current file as..."));
    /*
    fileMenu->AppendSeparator();
    fileMenu->Append(wxID_PRINT, wxT("Print\tCtrl+P"), wxT("Print current document"));
    fileMenu->Append(wxID_PRINT_SETUP, wxT("Print Setup\tShift+Ctrl+P"), wxT("Set printing options"));
    fileMenu->Append(wxID_PREVIEW, wxT("Print Pre&view"), wxT("Preview the printout of the current document"));
    fileMenu->AppendSeparator();*/
    fileMenu->Append(wxID_EXIT, wxT("E&xit\tCtrl+Q"),wxT("Quit this program"));


    //Edit Menu
    /*
    #if wxUSE_CLIPBOARD
        wxMenu *edit_menu = new wxMenu;
        edit_menu->Append(wxID_CUT, wxT("Cut\tCtrl+X"), wxT("Cut the selected text"));
        edit_menu->Append(wxID_COPY, wxT("Copy\tCtrl+C"), wxT("Copy the selected text"));
        edit_menu->Append(wxID_PASTE, wxT("Paste\tCtrl+V"), wxT("Paste text from the clipboard"));
    #endif
    */

    //Help Menu
    wxMenu *help_Menu = new wxMenu;
    help_Menu->Append(wxID_ABOUT, wxT("&About...\tF1"),wxT("Show about dialog"));

    //Now append the freshly created menu to the menu bar
    wxMenuBar *menu_Bar = new wxMenuBar();
    menu_Bar->Append(fileMenu, wxT("&File"));
    /*if(edit_menu){
        menu_Bar->Append(edit_menu, wxT("&Edit"));
    }*/
    menu_Bar->Append(help_Menu, wxT("&Help"));

    #ifdef __WXMAC__
        wxMenuBar::MacSetCommonMenuBar (menu_Bar);
    #endif

    //attach menu bar to frame
    SetMenuBar(menu_Bar);

    //Create status bar just for fun
    CreateStatusBar();
    SetStatusText(wxT("Welcome to CWebGUI!"));

    CenterOnScreen();

    Notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_LEFT);
    m_text = new wxTextCtrl(Notebook,
                wxID_ANY,             // ID
                _T(""),                 // Initial text
                wxDefaultPosition,      // Position
                wxDefaultSize,   // Size
                wxTE_MULTILINE);        // Flags 
    
    // Create new imagelist which takes images of 16x16 pixels
    m_imageList = new wxImageList(8, 8);
    m_imageList->Add(wxICON(close)); // Add image 0

    // Set it as the notebook's imagelist
    Notebook->SetImageList(m_imageList); 

    #if wxUSE_TOOLBAR
        CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL);
        InitToolBar(GetToolBar());
    #endif // wxUSE_TOOLBAR
    gs_nFrames = 0;
}


void MyFrame::OnNew(wxCommandEvent& event){

    Notebook->AddPage(m_text,
        wxString::Format(_T("Untitled %d"), gs_nFrames++), // Title
        true, // Select the tab (true/false)
        0); // Image index in image list we assigned with SetImageList() before
} 

void MyFrame::OnOpen(wxCommandEvent& event){
    wxString wildcards = wxT("HTML files (*.html, *.htm)|*.htm*|CSS files (*.css)|*.css|PHP files (*.php)|*.php|Other (*.*)|*.*");

    wxString file = ::wxFileSelector(wxT("Open file"), wxT(""), wxT(""), wxT(""), wildcards);
    if (file.IsEmpty() == false){
        m_text->LoadFile(file);
        wxString title;
        title.Printf(file, ++gs_nFrames);
    
         wxString::Format(_T("Untitled %d"), gs_nFrames++, true, 0);
         // Image index in image list we assigned with SetImageList() before
    } 
}

void MyFrame::OnSave(wxCommandEvent& event){
    wxString wildcards = wxT("HTML files (*.html, *.htm)|*.htm*|CSS files (*.css)|*.css|PHP files (*.php)|*.php|Other (*.*)|*.*");
    wxString file = ::wxFileSelector(wxT("Save file"), wxT(""), wxT(""), wxT(""), wildcards);
    if (file.IsEmpty() == false){
        m_text->SaveFile(file);
    }
}


/* MyFrame destructor */
MyFrame::~MyFrame() {
    // Have to delete the wxImageList
    delete m_imageList;
}
 
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 7:21 pm

You may have to add #include <wx/imaglist.h>

I'm using wxWidgets built from SVN (2.9) so it's probably included somewhere else (didn't have to add it here).

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 7:32 pm

ArKay wrote:You may have to add #include <wx/imaglist.h>

I'm using wxWidgets built from SVN (2.9) so it's probably included somewhere else (didn't have to add it here).
Is there a function directly derived from the imagelist to detect a click?
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 8:13 pm

No, a wxImageList is just a list of images (a stupid container so to speak). It has nothing to do with events.

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 9:11 pm

ArKay wrote:No, a wxImageList is just a list of images (a stupid container so to speak). It has nothing to do with events.
So how would I route that event to that image?
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 9:18 pm

You don't since the image itself isn't a control, you handle mouse events on the wxNotebook instead.

There's a flag which is supposed to tell if you clicked on the image of a page, but it doesn't seem to work if the notebook is attached on the left or right side of the window. :roll:

Well, that flag only works on Windows anyway. What you could do instead is to handle a double-click on the page control.

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 9:22 pm

ArKay wrote:You don't since the image itself isn't a control, you handle mouse events on the wxNotebook instead.

There's a flag which is supposed to tell if you clicked on the image of a page, but it doesn't seem to work if the notebook is attached on the left or right side of the window. :roll:

Well, that flag only works on Windows anyway. What you could do instead is to handle a double-click on the page control.
So how am I supposed to have a way to close each tab by clicking on it? ](*,)
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 9:28 pm

Well, single-click is out of question since you can't find out what you clicked on if you're not on Windows and/or have the Notebook attached to the left (as in your code) you should do it with a double-click handler.

Define double-click handler in the header file:

Code: Select all

    //Help Menu
    void OnAbout (wxCommandEvent& event);

    //Notebook double-click
    void OnNotebookDoubleClick(wxMouseEvent& event);
Add code in class:

Code: Select all

    m_imageList = new wxImageList(16, 16);
    m_imageList->Add(wxBitmap(child_xpm)); // Image 0

    Notebook->SetImageList(m_imageList);

    // Connect left-double-click event to MyFrame method
    Notebook->Connect(wxID_ANY, wxEVT_LEFT_DCLICK, wxMouseEventHandler(MyFrame::OnNotebookDoubleClick), NULL, this);
Add implementation:

Code: Select all

void MyFrame::OnNotebookDoubleClick(wxMouseEvent& event) {
    int nTabPosition = Notebook->HitTest(event.GetPosition());
    if (wxNOT_FOUND != nTabPosition) {
        // We hit a tab, delete it
        Notebook->DeletePage(nTabPosition);
    } else {
        // Not a tab, pass the event on
        event.Skip();
    }
}

timw4mail
Experienced Solver
Experienced Solver
Posts: 99
Joined: Sun Mar 23, 2008 6:59 pm
Location: United States
Contact:

Post by timw4mail » Sat Apr 05, 2008 9:36 pm

You've been such a big help, thanks :)
My wxWidgets Program:Snaga

Platforms:Windows, Linux, Solaris, Mac
IDE/Compiler:Netbeans with MinGW/GCC, Sun Compilers for Solaris, Xcode for Mac
wxWidgets Version:2.8.7

ArKay
Knows some wx things
Knows some wx things
Posts: 41
Joined: Wed Mar 26, 2008 1:38 pm
Location: Germany

Post by ArKay » Sat Apr 05, 2008 9:37 pm

No problem :)

Post Reply