Search code examples
javapositionswtcaretstyledtext

SWT StyledText: Position caret of the next line to tab width of the previous line


I am developing an (rich) editor based on SWT StyledText. There is one feature that I until now cannot solve it. I want my editor to place the cursor at the tab width as the beginning of the previous line when the user presses Ctrl+u (similar to Eclipse or Notepad++ when users press Enter key). I've tried several methods but nothing works for me. Please take a look at my example. Every suggestion is welcome. Thanks in advance.

StyledText text = new StyledText(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
    text.setTabs(5);
    text.setText("");
    text.setLeftMargin(5);
    text.setBounds(0, 0, 512, 391);
    text.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            int currentLine = text.getLineAtOffset(text.getCaretOffset());
            int currCaretOffset = text.getCaretOffset();
            if(e.stateMask == SWT.CTRL && e.keyCode == 'u'){
                //text.setIndent(text.getOffsetAtLine(currentLine));//doesn't work
                text.append("\n");
                //text.append("\t");//doesn't work
                text.setCaretOffset(text.getCharCount()+text.getTabs());//doesn't work
                System.out.println("caret offset "+text.getCaretOffset());
            }               
        }
    });

Solution

  • If I understand you correctly, you'd like to move the cursor to the next line and indent it by as many "white spaces" as there are leading spaces in the previous line.

    I'm surprised there isn't a better way to do this (or maybe I just haven't found one), but this will do the job:

    private static final int TAB_WIDTH = 5;
    
    public static void main(String[] args)
    {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setText("Stackoverflow");
        shell.setLayout(new FillLayout());
    
        StyledText text = new StyledText(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        text.setTabs(TAB_WIDTH);
        text.setText("");
        text.setLeftMargin(5);
        text.setBounds(0, 0, 512, 391);
        text.addListener(SWT.KeyUp, (e) -> {
            if (e.stateMask == SWT.CTRL && e.keyCode == 'u')
            {
                int currentLine = text.getLineAtOffset(text.getCaretOffset());
                String textAtLine = text.getLine(currentLine);
                int spaces = getLeadingSpaces(textAtLine);
                text.insert("\n");
                text.setCaretOffset(text.getCaretOffset() + 1);
                for (int i = 0; i < spaces; i++)
                    text.append(" ");
    
                text.setCaretOffset(text.getCaretOffset() + spaces);
            }
        });
    
        shell.pack();
        shell.open();
        shell.setSize(400, 300);
    
        while (!shell.isDisposed())
        {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
    
    private static int getLeadingSpaces(String line)
    {
        int counter = 0;
    
        char[] chars = line.toCharArray();
        for (char c : chars)
        {
            if (c == '\t')
                counter += TAB_WIDTH;
            else if (c == ' ')
                counter++;
            else
                break;
        }
    
        return counter;
    }