0

In the following code:

void Script::OnLeftUp( wxMouseEvent& event )
{
    int currentPos = GetCurrentPos();
    int wordStartPos = WordStartPosition( currentPos, true );
    int wordEndPos=WordEndPosition(wordStartPos, true);
    wxString identifier=GetRange(wordStartPos,wordEndPos);
    SetSelection(wordStartPos, wordEndPos );
    event.Skip();
}

When I click on a point inside a word (say for example the word is hello, and I left click between e and l) the identifier is correctly identified as hello. However, only he is selected, whereas I would expect the whole word hello to be selected. What could be going wrong? If the positions were wrong, then the value of the identifier should have been wrong, which is not the case.

By the way, I am using wxWidgets 3.1 on Windows 10.

macroland
  • 973
  • 9
  • 27
  • you function is "OnLeftUp()", but you are talking about the right mouse button. Which one is it? – Igor Sep 17 '16 at 13:48
  • I am not talking about right button, sorry for the misunderstanding. – macroland Sep 17 '16 at 22:14
  • did you try the stc sample? Try to put in the ekhumoro's solution if the plain sample does not perform as expected. – Igor Sep 18 '16 at 05:46

2 Answers2

0

According to the docs for SetSelection:

Notice that the insertion point will be moved to from by this function

Not exactly sure why, but this seems to be affecting the final selection somehow. You could try re-writing the function like this:

void Script::OnLeftUp( wxMouseEvent& event )
{
    int currentPos = GetCurrentPos();
    int wordStartPos = WordStartPosition( currentPos, true );
    int wordEndPos = WordEndPosition( currentPos, true );
    wxString identifier = GetRange( wordStartPos, wordEndPos );
    SetSelectionStart( wordStartPos );
    SetSelectionEnd( wordEndPos );
    event.Skip();
}
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • I have tried that way too, but it did not work either. – macroland Sep 17 '16 at 22:16
  • @macroland. I can't test using wxStyledTextCtrl, but the equivalent commands work exactly as expected in QScintilla (as does `SetSelection`). So the problem is either in some other part of your code, or there's a bug in wxStyledTextCtrl. (PS: tested using QScintilla-2.9.3 + Scintilla-3.5.4). – ekhumoro Sep 17 '16 at 22:42
  • My assumption is something to do with `InsertionPoint`. The selection occurs from the point where the caret is to the beginning of the word. I tried to move the caret to the end of the word, could not achieve that. By the way, did you try it for the `OnLeftUp` event? – macroland Sep 18 '16 at 02:44
  • @macroland. The problem may be that the normal handling of the mouse event is being disrupted. I think you need to process the mouse event first (so that the underlying Scintilla control is properly updated), then do your new selection. – ekhumoro Sep 18 '16 at 03:10
  • I tried it by moving `event.Skip()` to the first line; that did not help either. The selection occurs from the blinking cursor to the start of the word. If I find a way to move the cursor to the end of the word, then it will select the whole word. I tried `SetInsertionPoint` and `SetCurrentPos` but did not work either. – macroland Sep 18 '16 at 03:18
  • @macroland. Try testing the word selection code outside of a mouse event handler. This should at least confirm that the commands are all working correctly, and that the problem lies elsewhere. You could also try using `OnLeftClick`. – ekhumoro Sep 18 '16 at 04:01
0

What you want to do isn't exactly possible. In scintilla/wxStyledTextCtrl a selection always runs from somewhere to the current caret position. You're trying to make a selection that starts before the current position and ends after it, and that just can't be done.

Also this is basically the default behavior when you double click a word with the exception that the double click will move the caret to the end of the word. Do you really need to do this with a single click? If you really want to, you can use multiple selections to give the appearance of this however. Basically you will have one selection that runs from the start of the word to the current position, and a second selection from the current position until the end.

Put these commands somewhere that gets called before the mouse handler (probably in the constructor) and also declare a method with this prototype "void SelectCurWord();"

SetSelBackground(true, wxColour(192,192,192) );
SetSelForeground(true, wxColour(0,0,0) );

SetAdditionalSelBackground( wxColor(192,192,192) );
SetAdditionalSelForeground( wxColour(0,0,0) );
SetAdditionalCaretsVisible(false);

You can change the colors to whatever you want, but make sure the primary and additional selections use the same colors. The mouse handler should do something like this.

void Script::OnLeftUp( wxMouseEvent& event )
{
    CallAfter(&Script::SelectCurWord);
    event.Skip();
}

The reason we have to use the CallAfter is to let the event processing complete its work before trying to add selections. The SelectCurWord method is basically what you had before but uses multiple selections instead:

void Script::SelectCurWord()
{
    int currentPos = GetCurrentPos();
    int wordStartPos = WordStartPosition( currentPos, true );
    int wordEndPos=WordEndPosition(wordStartPos, true);

    AddSelection(wordStartPos,currentPos);
    AddSelection(currentPos,wordEndPos);
}
New Pagodi
  • 3,484
  • 1
  • 14
  • 24
  • I agree with you. It was also my observation that the way I tried was either selecting from the current position to the beginning of the word or to the end of the word. I was actually trying to highlight the words (thinking that this would be a selection); however, I realized that it was not a good idea at all and moreover have achieved that using indicators which works like a charm. – macroland Sep 19 '16 at 22:46