Index: libsrc/org/netbeans/editor/ActionFactory.java =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/editor/ActionFactory.java,v retrieving revision 1.80 diff -u -u -r1.80 ActionFactory.java --- libsrc/org/netbeans/editor/ActionFactory.java 19 Jan 2007 05:21:30 -0000 1.80 +++ libsrc/org/netbeans/editor/ActionFactory.java 14 Feb 2007 08:40:02 -0000 @@ -31,6 +31,7 @@ import javax.swing.ActionMap; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Element; import javax.swing.text.JTextComponent; import javax.swing.text.Document; import javax.swing.text.Caret; @@ -307,6 +308,365 @@ doc.remove(bolPos, eolPos - bolPos); } catch (BadLocationException e) { target.getToolkit().beep(); + } finally { + DocumentUtilities.setTypingModification(doc, false); + doc.atomicUnlock(); + } + } + } + } + + public static class MoveSelectionElseLineUpAction extends LocalBaseAction { + + static final long serialVersionUID =-1; // TODO + + public MoveSelectionElseLineUpAction() { + super(BaseKit.moveSelectionElseLineUpAction, MAGIC_POSITION_RESET + | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + } + + public void actionPerformed(ActionEvent evt, JTextComponent target) { + if (target != null) { + if (!target.isEditable() || !target.isEnabled()) { + target.getToolkit().beep(); + return; + } + BaseDocument doc = (BaseDocument) target.getDocument(); + doc.atomicLock(); + DocumentUtilities.setTypingModification(doc, true); + try { + Element rootElement = doc.getDefaultRootElement(); + + Caret caret = target.getCaret(); + boolean selection = false; + boolean backwardSelection = false; + int start = target.getCaretPosition(); + int end = start; + + // check if there is a selection + if (caret.isSelectionVisible()) { + int selStart = caret.getDot(); + int selEnd = caret.getMark(); + start = Math.min(selStart, selEnd); + end = Math.max(selStart, selEnd) - 1; + selection = true; + backwardSelection = (selStart >= selEnd); + } + + int zeroBaseStartLineNumber = rootElement.getElementIndex(start); + int zeroBaseEndLineNumber = rootElement.getElementIndex(end); + + if (zeroBaseStartLineNumber == -1) { + // could not get line number + target.getToolkit().beep(); + return; + } else if (zeroBaseStartLineNumber == 0) { + // already first line + return; + } else { + try { + // get line text + Element startLineElement = rootElement.getElement(zeroBaseStartLineNumber); + int startLineStartOffset = startLineElement.getStartOffset(); + + Element endLineElement = rootElement.getElement(zeroBaseEndLineNumber); + int endLineEndOffset = endLineElement.getEndOffset(); + + String linesText = doc.getText(startLineStartOffset, (endLineEndOffset - startLineStartOffset)); + + Element previousLineElement = rootElement.getElement(zeroBaseStartLineNumber - 1); + int previousLineStartOffset = previousLineElement.getStartOffset(); + + int column = start - startLineStartOffset; + + // remove the line + doc.remove(startLineStartOffset, Math.min(doc.getLength(),endLineEndOffset) - startLineStartOffset); + + // insert the text before the previous line + doc.insertString(previousLineStartOffset, linesText, null); + + if (selection) { + // select moved lines + if (backwardSelection) { + caret.setDot(previousLineStartOffset + column); + caret.moveDot(previousLineStartOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + } else { + caret.setDot(previousLineStartOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + caret.moveDot(previousLineStartOffset + column); + } + } else { + // set caret position + target.setCaretPosition(previousLineStartOffset + column); + } + } catch (BadLocationException ex) { + target.getToolkit().beep(); + } + } + } finally { + DocumentUtilities.setTypingModification(doc, false); + doc.atomicUnlock(); + } + } + } + } + + public static class MoveSelectionElseLineDownAction extends LocalBaseAction { + + static final long serialVersionUID =-1; // TODO + + public MoveSelectionElseLineDownAction() { + super(BaseKit.moveSelectionElseLineDownAction, MAGIC_POSITION_RESET + | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + } + + public void actionPerformed(ActionEvent evt, JTextComponent target) { + if (target != null) { + if (!target.isEditable() || !target.isEnabled()) { + target.getToolkit().beep(); + return; + } + BaseDocument doc = (BaseDocument) target.getDocument(); + doc.atomicLock(); + DocumentUtilities.setTypingModification(doc, true); + try { + Element rootElement = doc.getDefaultRootElement(); + + Caret caret = target.getCaret(); + boolean selection = false; + boolean backwardSelection = false; + int start = target.getCaretPosition(); + int end = start; + + // check if there is a selection + if (caret.isSelectionVisible()) { + int selStart = caret.getDot(); + int selEnd = caret.getMark(); + start = Math.min(selStart, selEnd); + end = Math.max(selStart, selEnd) - 1; + selection = true; + backwardSelection = (selStart >= selEnd); + } + + int zeroBaseStartLineNumber = rootElement.getElementIndex(start); + int zeroBaseEndLineNumber = rootElement.getElementIndex(end); + + if (zeroBaseEndLineNumber == -1) { + // could not get line number + target.getToolkit().beep(); + return; + } else if (zeroBaseEndLineNumber >= (rootElement.getElementCount() - 2)) { + // already last or penultimate line (due to a getLength() bug) + return; + } else { + try { + // get line text + Element startLineElement = rootElement.getElement(zeroBaseStartLineNumber); + int startLineStartOffset = startLineElement.getStartOffset(); + + Element endLineElement = rootElement.getElement(zeroBaseEndLineNumber); + int endLineEndOffset = endLineElement.getEndOffset(); + + String linesText = doc.getText(startLineStartOffset, (endLineEndOffset - startLineStartOffset)); + + Element nextLineElement = rootElement.getElement(zeroBaseEndLineNumber + 1); + int nextLineStartOffset = nextLineElement.getStartOffset(); + int nextLineEndOffset = nextLineElement.getEndOffset(); + + int column = start - startLineStartOffset; + + // insert it after next line + doc.insertString(nextLineEndOffset, linesText, null); + + // remove original line + doc.remove(startLineStartOffset, (endLineEndOffset - startLineStartOffset)); + + if (selection) { + // select moved lines + if (backwardSelection) { + caret.setDot(nextLineEndOffset - (endLineEndOffset - startLineStartOffset) + column); + caret.moveDot(nextLineEndOffset - (endLineEndOffset - end - 1)); + } else { + caret.setDot(nextLineEndOffset - (endLineEndOffset - end - 1)); + caret.moveDot(nextLineEndOffset - (endLineEndOffset - startLineStartOffset) + column); + } + } else { + // set caret position + target.setCaretPosition(Math.min(doc.getLength() - 1, nextLineEndOffset + column - (endLineEndOffset - startLineStartOffset))); + } + } catch (BadLocationException ex) { + target.getToolkit().beep(); + } + } + } finally { + DocumentUtilities.setTypingModification(doc, false); + doc.atomicUnlock(); + } + } + } + } + + public static class CopySelectionElseLineUpAction extends LocalBaseAction { + + static final long serialVersionUID =-1; // TODO + + public CopySelectionElseLineUpAction() { + super(BaseKit.copySelectionElseLineUpAction, MAGIC_POSITION_RESET + | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + } + + public void actionPerformed(ActionEvent evt, JTextComponent target) { + if (target != null) { + if (!target.isEditable() || !target.isEnabled()) { + target.getToolkit().beep(); + return; + } + BaseDocument doc = (BaseDocument) target.getDocument(); + doc.atomicLock(); + DocumentUtilities.setTypingModification(doc, true); + try { + Element rootElement = doc.getDefaultRootElement(); + + Caret caret = target.getCaret(); + boolean selection = false; + boolean backwardSelection = false; + int start = target.getCaretPosition(); + int end = start; + + // check if there is a selection + if (caret.isSelectionVisible()) { + int selStart = caret.getDot(); + int selEnd = caret.getMark(); + start = Math.min(selStart, selEnd); + end = Math.max(selStart, selEnd) - 1; + selection = true; + backwardSelection = (selStart >= selEnd); + } + + int zeroBaseStartLineNumber = rootElement.getElementIndex(start); + int zeroBaseEndLineNumber = rootElement.getElementIndex(end); + + if (zeroBaseStartLineNumber == -1) { + // could not get line number + target.getToolkit().beep(); + return; + } else { + try { + // get line text + Element startLineElement = rootElement.getElement(zeroBaseStartLineNumber); + int startLineStartOffset = startLineElement.getStartOffset(); + + Element endLineElement = rootElement.getElement(zeroBaseEndLineNumber); + int endLineEndOffset = endLineElement.getEndOffset(); + + String linesText = doc.getText(startLineStartOffset, (endLineEndOffset - startLineStartOffset)); + + int column = start - startLineStartOffset; + + // insert it + doc.insertString(startLineStartOffset, linesText, null); + + if (selection) { + // select moved lines + if (backwardSelection) { + caret.setDot(startLineStartOffset + column); + caret.moveDot(startLineStartOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + } else { + caret.setDot(startLineStartOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + caret.moveDot(startLineStartOffset + column); + } + } else { + // set caret position + target.setCaretPosition(startLineStartOffset + column); + } + } catch (BadLocationException ex) { + target.getToolkit().beep(); + } + } + } finally { + DocumentUtilities.setTypingModification(doc, false); + doc.atomicUnlock(); + } + } + } + } + + public static class CopySelectionElseLineDownAction extends LocalBaseAction { + + static final long serialVersionUID =-1; // TODO + + public CopySelectionElseLineDownAction() { + super(BaseKit.copySelectionElseLineDownAction, MAGIC_POSITION_RESET + | ABBREV_RESET | UNDO_MERGE_RESET | WORD_MATCH_RESET); + } + + public void actionPerformed(ActionEvent evt, JTextComponent target) { + if (target != null) { + if (!target.isEditable() || !target.isEnabled()) { + target.getToolkit().beep(); + return; + } + BaseDocument doc = (BaseDocument) target.getDocument(); + doc.atomicLock(); + DocumentUtilities.setTypingModification(doc, true); + try { + Element rootElement = doc.getDefaultRootElement(); + + Caret caret = target.getCaret(); + boolean selection = false; + boolean backwardSelection = false; + int start = target.getCaretPosition(); + int end = start; + + // check if there is a selection + if (caret.isSelectionVisible()) { + int selStart = caret.getDot(); + int selEnd = caret.getMark(); + start = Math.min(selStart, selEnd); + end = Math.max(selStart, selEnd) - 1; + selection = true; + backwardSelection = (selStart >= selEnd); + } + + int zeroBaseStartLineNumber = rootElement.getElementIndex(start); + int zeroBaseEndLineNumber = rootElement.getElementIndex(end); + + if (zeroBaseEndLineNumber == -1) { + // could not get line number + target.getToolkit().beep(); + return; + } else { + try { + // get line text + Element startLineElement = rootElement.getElement(zeroBaseStartLineNumber); + int startLineStartOffset = startLineElement.getStartOffset(); + + Element endLineElement = rootElement.getElement(zeroBaseEndLineNumber); + int endLineEndOffset = endLineElement.getEndOffset(); + + String linesText = doc.getText(startLineStartOffset, (endLineEndOffset - startLineStartOffset)); + + int column = start - startLineStartOffset; + + // insert it after next line + doc.insertString(endLineEndOffset, linesText, null); + + if (selection) { + // select moved lines + if (backwardSelection) { + caret.setDot(endLineEndOffset + column); + caret.moveDot(endLineEndOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + } else { + caret.setDot(endLineEndOffset + (endLineEndOffset - startLineStartOffset) - (endLineEndOffset - end - 1)); + caret.moveDot(endLineEndOffset + column); + } + } else { + // set caret position + target.setCaretPosition(Math.min(doc.getLength() - 1, endLineEndOffset + column)); + } + } catch (BadLocationException ex) { + target.getToolkit().beep(); + } + } } finally { DocumentUtilities.setTypingModification(doc, false); doc.atomicUnlock(); Index: libsrc/org/netbeans/editor/BaseKit.java =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/editor/BaseKit.java,v retrieving revision 1.158 diff -u -u -r1.158 BaseKit.java --- libsrc/org/netbeans/editor/BaseKit.java 22 Jan 2007 23:37:41 -0000 1.158 +++ libsrc/org/netbeans/editor/BaseKit.java 14 Feb 2007 08:40:06 -0000 @@ -114,6 +114,18 @@ /** Remove line */ public static final String removeLineAction = "remove-line"; // NOI18N + + /** Move selection else line up */ + public static final String moveSelectionElseLineUpAction = "move-selection-else-line-up"; // NOI18N + + /** Move selection else line down */ + public static final String moveSelectionElseLineDownAction = "move-selection-else-line-down"; // NOI18N + + /** Copy selection else line up */ + public static final String copySelectionElseLineUpAction = "copy-selection-else-line-up"; // NOI18N + + /** Copy selection else line down */ + public static final String copySelectionElseLineDownAction = "copy-selection-else-line-down"; // NOI18N /** Toggle the typing mode to overwrite mode or back to insert mode */ public static final String toggleTypingModeAction = "toggle-typing-mode"; // NOI18N @@ -648,6 +660,10 @@ new ActionFactory.RemoveWordNextAction(), new ActionFactory.RemoveLineBeginAction(), new ActionFactory.RemoveLineAction(), + new ActionFactory.MoveSelectionElseLineUpAction(), + new ActionFactory.MoveSelectionElseLineDownAction(), + new ActionFactory.CopySelectionElseLineUpAction(), + new ActionFactory.CopySelectionElseLineDownAction(), removeSelectionActionDef, new ActionFactory.ToggleTypingModeAction(), new ActionFactory.AbbrevExpandAction(), Index: libsrc/org/netbeans/editor/Bundle.properties =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/editor/Bundle.properties,v retrieving revision 1.72 diff -u -u -r1.72 Bundle.properties --- libsrc/org/netbeans/editor/Bundle.properties 22 Jan 2007 09:58:32 -0000 1.72 +++ libsrc/org/netbeans/editor/Bundle.properties 14 Feb 2007 08:40:07 -0000 @@ -103,6 +103,10 @@ redo=Redo reindent-line=Re-indent Current Line or Selection remove-line=Delete Line +move-selection-else-line-up=Move Selection else Line up +move-selection-else-line-down=Move Selection else Line down +copy-selection-else-line-up=Copy Selection else Line up +copy-selection-else-line-down=Copy Selection else Line down remove-line-begin=Delete Preceding Characters in Line remove-selection=Delete Selection remove-tab=Delete Tab Index: src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml =================================================================== RCS file: /cvs/editor/src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml,v retrieving revision 1.5 diff -u -u -r1.5 NetBeans-keybindings.xml --- src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml 22 Jan 2007 09:58:32 -0000 1.5 +++ src/org/netbeans/modules/editor/resources/NetBeans-keybindings.xml 14 Feb 2007 08:41:16 -0000 @@ -75,9 +75,10 @@ - - - + + + +