Search code examples
c++cgtkwxwidgets

Retrieving client area coordinates of a character position from text control


I am in need of writing a function which can get screen coordinates from the character position in a text edit control. I am using text edit control provided by wxWidgets framework. The wxTextCtrl is not exposing any API functions which can provide this information. On Windows, I can get the information by sending EM_POSFROMCHAR to the text control.

I am wondering how the same can be done on other environments like Linux. For now this needs to be done on only the desktop environments which runs on top of X Window System like GNOME, KDE and XFCE. Is there a way to do it? And on these DE, who draws the controls like text edit? Is it managed by X and styled by particular DE?

Any help would be appreciated.


Solution

  • Well, it is possible, but you need to implement a wxTextCtrl derived control that relies on underlaying platform capabilities for any particular wxWidgets port (wxMSW, wxGTK, etc).

    So, because you have asked about Linux implementation. Let me explain how to implement it for wxGTK 2.9. Below is the wxTextCtrlExt control definition:

    #include <wx/textctrl.h>
    #include <wx/gdicmn.h>
    
    //-----------------------------------------------------------------------------
    // wxTextCtrlExt
    //-----------------------------------------------------------------------------
    
    class wxTextCtrlExt : public wxTextCtrl
    {
    public:
        wxTextCtrlExt() : wxTextCtrl() { }
        wxTextCtrlExt(wxWindow* parent,
                      wxWindowID id,
                      const wxString& value = wxEmptyString,
                      const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
                      long style = wxTE_MULTILINE,
                      const wxValidator& validator = wxDefaultValidator,
                      const wxString& name = wxTextCtrlNameStr)
        : wxTextCtrl(parent, id, value, pos, size, style, validator, name ) { }
    
        wxPoint GetPositionCoords(long pos);
    };
    

    And the wxGTK implementation:

    #include "wxTextCtrlExt.h"
    #include <wx/defs.h>
    
    #include <gtk/gtk.h>
    
    wxPoint wxTextCtrlExt::GetPositionCoords(long pos)
    {
        if ( IsMultiLine() ) {
            GtkTextView* txtView = GTK_TEXT_VIEW(m_focusWidget);
            GtkTextBuffer* txtBuffer = gtk_text_view_get_buffer(txtView);
    
            GtkTextIter iter;
            gtk_text_buffer_get_iter_at_offset(txtBuffer, &iter, pos);
    
            GdkRectangle location; // output location in buffer coordinates
            gtk_text_view_get_iter_location(txtView, &iter, &location);
    
            return wxPoint(location.x, location.y);
        }
    
        return wxPoint(0,0);
    }
    

    You may also want to convert your buffer coordinates to a widget's ones:

        // If we need to convert our coordinates to 
        GdkPoint out;
        gtk_text_view_buffer_to_window_coords(txtView, GTK_TEXT_WINDOW_WIDGET, location.x, location.y, &out.x, &out.y );
    
        return wxPoint(out.x, out.y);
    

    As you can see, this particular implementation does not account for a single line text entry, that's why you need to use a wxTE_MULTILINE style when you are creating the wxTextCtrlExt control.

    Well, below is how to use it. Let's m_Text2 be the pointer to a child object of wxTextCtrlExt class:

    long iCharPos = m_Text2->GetInsertionPoint();
    long iCharPosMax = m_Text2->GetLastPosition();
    wxPoint pos = m_Text2->GetPositionCoords(iCharPos);
    

    Now we got our character position coordinates in pos. That's it!

    Some links that maybe of any interest to you:

    Now it is all about your second question.

    And on these DE, who draws the controls like text edit? Is it managed by X and styled by particular DE?

    This depends on the wxWidgets port you are using. The wxMSW and wxGTK ports use Win32 and GTK+2 native controls, respectively. The wxUniversal based ports (such as wxX11, wxMGL) draw all the controls by wxWidgets itself. X Window System does not mandate the user interface by itself. It provides the basic framework for building GUI environments: drawing and moving windows on the screen and interacting with a mouse and keyboard.