From 299bd92ca55432386eb7a4df4e67ea5283e70e8d Mon Sep 17 00:00:00 2001 From: Oliver Oppitz Date: Sun, 9 Jun 2024 12:50:35 +0900 Subject: [PATCH 1/2] feat: Optionally allow selecting segment with a single click - Add Preference.SINGLE_CLICK_SEGMENT_ACTIVATION - Add checkbox for controlling single-click-activation of segments - Make single-click activation of segments depends on cursor-lock-mode - Allow single click to activate segment - Single click moves cursor to the word pointed Signed-off-by: Hiroshi Miura --- .../omegat/gui/editor/EditorController.java | 32 +++++++++++++- .../omegat/gui/editor/EditorTextArea3.java | 19 ++++++++ src/org/omegat/gui/editor/IEditor.java | 11 +++++ .../view/EditingBehaviorController.java | 43 ++++++++++++++++++- .../view/EditingBehaviorPanel.form | 43 +++++++++++-------- .../view/EditingBehaviorPanel.java | 30 +++++++------ src/org/omegat/util/Preferences.java | 5 +++ test/data/preferences/omegat.prefs.xml | 1 + 8 files changed, 151 insertions(+), 33 deletions(-) diff --git a/src/org/omegat/gui/editor/EditorController.java b/src/org/omegat/gui/editor/EditorController.java index c1e16448a8..7e8bb4a1f4 100644 --- a/src/org/omegat/gui/editor/EditorController.java +++ b/src/org/omegat/gui/editor/EditorController.java @@ -758,6 +758,11 @@ private void insertStartParagraphMark(Document3 doc, SegmentBuilder sb, int star */ public void activateEntry() { activateEntry(CaretPosition.startOfEntry()); + + } + + public void activateEntryAndGotoOffset(int offset) { + activateEntry(CaretPosition.goToCharacterAtIndex(offset)); } /** @@ -996,7 +1001,7 @@ public void showStat() { * Go to segment at specified location. * * @param location - * location + * location relative to the whole document * @return true if segment changed, false if location inside current segment */ protected boolean goToSegmentAtLocation(int location) { @@ -1016,6 +1021,31 @@ protected boolean goToSegmentAtLocation(int location) { } } + protected boolean goToSegmentAtLocationAndJumpToOffset(int location, int offset) { + // clicked segment + + int segmentAtLocation = getSegmentIndexAtLocation(location); + if (segmentAtLocation < 0) { + return false; + } + if (displayedEntryIndex != segmentAtLocation) { + commitAndDeactivate(); + displayedEntryIndex = segmentAtLocation; + activateEntryAndGotoOffset(offset); + return true; + } else { + return false; + } + } + + protected int getStartForSegmentWithIndex(int segmentIndex) { + if (m_docSegList == null) { + return -1; + } + SegmentBuilder builder = m_docSegList[segmentIndex]; + return builder.getStartPosition(); + } + protected int getSegmentIndexAtLocation(int location) { if (m_docSegList == null) { return -1; diff --git a/src/org/omegat/gui/editor/EditorTextArea3.java b/src/org/omegat/gui/editor/EditorTextArea3.java index f7d7e4fe31..0f98d0302e 100644 --- a/src/org/omegat/gui/editor/EditorTextArea3.java +++ b/src/org/omegat/gui/editor/EditorTextArea3.java @@ -70,6 +70,8 @@ import org.omegat.util.StringUtil; import org.omegat.util.gui.Styles; import org.omegat.util.gui.UIDesignManager; +import org.omegat.util.Preferences; + /** * Changes of standard JEditorPane implementation for support custom behavior. @@ -228,6 +230,23 @@ public boolean isInActiveTranslation(int position) { public void mouseClicked(MouseEvent e) { autoCompleter.setVisible(false); + boolean singleClickSegmentActivation = + Preferences.isPreference(Preferences.SINGLE_CLICK_SEGMENT_ACTIVATION); + System.out.println("Preferences.SINGLE_CLICK_SEGMENT_ACTIVATION: " + (singleClickSegmentActivation ? "ENABLED" : "DISABLED")); + + if (singleClickSegmentActivation + && e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1 + && lockCursorToInputArea) { + int location = getCaretPosition(); + int mousepos = EditorTextArea3.this.viewToModel2D(e.getPoint()); + int segmentIndex = controller.getSegmentIndexAtLocation(location); + int startLocation = controller.getStartForSegmentWithIndex(segmentIndex); + int offset = mousepos - startLocation; + boolean changed = controller.goToSegmentAtLocationAndJumpToOffset(mousepos, offset); + if (changed) { + return; + } + } // Handle double-click if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { int mousepos = EditorTextArea3.this.viewToModel2D(e.getPoint()); diff --git a/src/org/omegat/gui/editor/IEditor.java b/src/org/omegat/gui/editor/IEditor.java index c7ac43c3cc..bffd039f70 100644 --- a/src/org/omegat/gui/editor/IEditor.java +++ b/src/org/omegat/gui/editor/IEditor.java @@ -86,6 +86,17 @@ public CaretPosition(int selectionStart, int selectionEnd) { public static CaretPosition startOfEntry() { return new CaretPosition(0); } + + /** + * Set caret to a specific character. + * @param location 0 when first character of String, otherwise + * location counts all text, both original language + * and translated text. + * @return caret position. + */ + public static CaretPosition goToCharacterAtIndex(int location) { + return new CaretPosition(location); + } } /** diff --git a/src/org/omegat/gui/preferences/view/EditingBehaviorController.java b/src/org/omegat/gui/preferences/view/EditingBehaviorController.java index a3a2a700a7..97d95fc816 100644 --- a/src/org/omegat/gui/preferences/view/EditingBehaviorController.java +++ b/src/org/omegat/gui/preferences/view/EditingBehaviorController.java @@ -30,6 +30,8 @@ package org.omegat.gui.preferences.view; +import static org.openide.awt.Mnemonics.setLocalizedText; + import javax.swing.JComponent; import org.omegat.gui.editor.SegmentBuilder; @@ -63,6 +65,7 @@ public String toString() { private void initGui() { panel = new EditingBehaviorPanel(); + initLabels(); panel.insertFuzzyCheckBox.addActionListener(e -> { panel.similarityLabel.setEnabled(panel.insertFuzzyCheckBox.isSelected()); panel.similaritySpinner.setEnabled(panel.insertFuzzyCheckBox.isSelected()); @@ -71,10 +74,40 @@ private void initGui() { }); } + /** + * Set localized labels from Bundle. + */ + private void initLabels() { + panel.descriptionTextArea.setText(OStrings.getString("GUI_WORKFLOW_DESCRIPTION")); + setLocalizedText(panel.defaultRadio, OStrings.getString("WF_OPTION_INSERT_SOURCE")); + setLocalizedText(panel.leaveEmptyRadio, OStrings.getString("WF_OPTION_INSERT_NOTHTHING")); + setLocalizedText(panel.insertFuzzyCheckBox, OStrings.getString("WF_OPTION_INSERT_FUZZY_MATCH")); + setLocalizedText(panel.similarityLabel, + OStrings.getString("GUI_WORKFLOW_OPTION_Minimal_Similarity")); + setLocalizedText(panel.prefixLabel, OStrings.getString("WF_OPTION_INSERT_FUZZY_PREFIX")); + setLocalizedText(panel.convertNumbers, OStrings.getString("WF_OPTION_REPLACE_NUMBERS")); + setLocalizedText(panel.allowTranslationEqualToSource, OStrings.getString( + "WF_OPTION_ALLOW_TRANS_EQ_TO_SRC")); + setLocalizedText(panel.exportCurrentSegment, OStrings.getString("WF_OPTION_EXPORT__CURRENT_SEGMENT")); + setLocalizedText(panel.stopOnAlternativeTranslation, OStrings.getString( + "WF_OPTION_GOTO_NEXT_UNTRANSLATED")); + setLocalizedText(panel.allowTagEditing, OStrings.getString("WF_TAG_EDITING")); + setLocalizedText(panel.tagValidateOnLeave, OStrings.getString("WG_TAG_VALIDATE_ON_LEAVE")); + setLocalizedText(panel.cbSaveAutoStatus, OStrings.getString("WG_SAVE_AUTO_STATUS")); + setLocalizedText(panel.cbSaveOrigin, OStrings.getString("WG_SAVE_ORIGIN")); + setLocalizedText(panel.initialSegCountLabel, OStrings.getString("WG_INITIAL_SEGMENT_LOAD_COUNT")); + panel.initialSegCountSpinner.setToolTipText(OStrings.getString( + "WG_INITIAL_SEGMENT_LOAD_COUNT_TOOLTIP")); + setLocalizedText(panel.paraMarkLabel, OStrings.getString("WG_PARA_MARK")); + setLocalizedText(panel.singleClickActivationCheckBox, OStrings.getString( + "WF_OPTION_ALLOW_SELECT_SINGLE_CLICK")); + } + @Override protected void initFromPrefs() { // Double negation? then prefInsertSource is the contrary of Preferences.DONT_INSERT_SOURCE_TEXT - boolean prefInsertSource = !Preferences.isPreferenceDefault(Preferences.DONT_INSERT_SOURCE_TEXT, SegmentBuilder.DONT_INSERT_SOURCE_TEXT_DEFAULT); + boolean prefInsertSource = !Preferences.isPreferenceDefault(Preferences.DONT_INSERT_SOURCE_TEXT, + SegmentBuilder.DONT_INSERT_SOURCE_TEXT_DEFAULT); panel.defaultRadio.setSelected(prefInsertSource); panel.leaveEmptyRadio.setSelected(!prefInsertSource); @@ -87,7 +120,10 @@ protected void initFromPrefs() { panel.prefixText.setText(Preferences.getPreference(Preferences.BEST_MATCH_EXPLANATORY_TEXT)); } - panel.allowTranslationEqualToSource.setSelected(Preferences.isPreferenceDefault(Preferences.ALLOW_TRANS_EQUAL_TO_SRC, true)); + panel.allowTranslationEqualToSource.setSelected( + Preferences.isPreferenceDefault(Preferences.ALLOW_TRANS_EQUAL_TO_SRC, true)); + panel.singleClickActivationCheckBox.setSelected( + Preferences.isPreferenceDefault(Preferences.SINGLE_CLICK_SEGMENT_ACTIVATION, false)); panel.exportCurrentSegment.setSelected(Preferences.isPreference(Preferences.EXPORT_CURRENT_SEGMENT)); panel.stopOnAlternativeTranslation .setSelected(Preferences.isPreference(Preferences.STOP_ON_ALTERNATIVE_TRANSLATION)); @@ -113,6 +149,7 @@ public void restoreDefaults() { panel.prefixText.setText(OStrings.getString("WF_DEFAULT_PREFIX")); panel.allowTranslationEqualToSource.setSelected(true); + panel.singleClickActivationCheckBox.setSelected(false); panel.exportCurrentSegment.setSelected(false); panel.stopOnAlternativeTranslation.setSelected(false); panel.convertNumbers.setSelected(true); @@ -147,6 +184,8 @@ public void persist() { Preferences.setPreference(Preferences.ALLOW_TRANS_EQUAL_TO_SRC, panel.allowTranslationEqualToSource.isSelected()); Preferences.setPreference(Preferences.EXPORT_CURRENT_SEGMENT, panel.exportCurrentSegment.isSelected()); + Preferences.setPreference(Preferences.SINGLE_CLICK_SEGMENT_ACTIVATION, + panel.singleClickActivationCheckBox.isSelected()); Preferences.setPreference(Preferences.STOP_ON_ALTERNATIVE_TRANSLATION, panel.stopOnAlternativeTranslation.isSelected()); Preferences.setPreference(Preferences.CONVERT_NUMBERS, panel.convertNumbers.isSelected()); diff --git a/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.form b/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.form index e620000d09..8f5b933f9c 100644 --- a/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.form +++ b/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.form @@ -34,13 +34,15 @@ - - - + + + + + @@ -53,9 +55,7 @@ - - - + @@ -79,9 +79,7 @@ - - - + @@ -99,13 +97,8 @@ - - - + - - - @@ -120,9 +113,7 @@ - - - + @@ -311,6 +302,9 @@ + + + @@ -375,5 +369,18 @@ + + + + + + + + + + + + + diff --git a/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.java b/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.java index 5479193824..9174005e1e 100644 --- a/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.java +++ b/src/org/omegat/gui/preferences/view/EditingBehaviorPanel.java @@ -80,6 +80,7 @@ private void initComponents() { filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 32767)); paraMarkLabel = new javax.swing.JLabel(); paraMarkText = new javax.swing.JTextField(); + singleClickActivationCheckBox = new javax.swing.JCheckBox(); setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10)); setLayout(new java.awt.GridBagLayout()); @@ -87,7 +88,8 @@ private void initComponents() { descriptionTextArea.setEditable(false); descriptionTextArea.setFont(prefixLabel.getFont()); descriptionTextArea.setLineWrap(true); - descriptionTextArea.setText(OStrings.getString("GUI_WORKFLOW_DESCRIPTION")); // NOI18N + descriptionTextArea.setText("descriptionTextArea"); // NOI18N + descriptionTextArea.setToolTipText(""); descriptionTextArea.setWrapStyleWord(true); descriptionTextArea.setFocusable(false); descriptionTextArea.setOpaque(false); @@ -102,7 +104,7 @@ private void initComponents() { ourButtonGroup.add(defaultRadio); defaultRadio.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(defaultRadio, OStrings.getString("WF_OPTION_INSERT_SOURCE")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(defaultRadio, "defaultRadio"); // NOI18N defaultRadio.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); defaultRadio.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -119,7 +121,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { add(defaultRadio, gridBagConstraints); ourButtonGroup.add(leaveEmptyRadio); - org.openide.awt.Mnemonics.setLocalizedText(leaveEmptyRadio, OStrings.getString("WF_OPTION_INSERT_NOTHTHING")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(leaveEmptyRadio, "leaveEmptyRadio"); // NOI18N leaveEmptyRadio.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -130,12 +132,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0); add(leaveEmptyRadio, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(insertFuzzyCheckBox, OStrings.getString("WF_OPTION_INSERT_FUZZY_MATCH")); // NOI18N - insertFuzzyCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - radiosActionPerformed(evt); - } - }); + org.openide.awt.Mnemonics.setLocalizedText(insertFuzzyCheckBox, "insertFuzzyCheckBox"); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; @@ -146,7 +143,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { add(insertFuzzyCheckBox, gridBagConstraints); similarityLabel.setLabelFor(similaritySpinner); - org.openide.awt.Mnemonics.setLocalizedText(similarityLabel, OStrings.getString("GUI_WORKFLOW_OPTION_Minimal_Similarity")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(similarityLabel, "similarityLabel"); // NOI18N similarityLabel.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -307,6 +304,14 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { gridBagConstraints.ipadx = 250; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; add(paraMarkText, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(singleClickActivationCheckBox, "jCheckBox1"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 16; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(singleClickActivationCheckBox, gridBagConstraints); }// //GEN-END:initComponents private void radiosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radiosActionPerformed @@ -320,10 +325,10 @@ private void radiosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST: javax.swing.JCheckBox cbSaveOrigin; javax.swing.JCheckBox convertNumbers; javax.swing.JRadioButton defaultRadio; - private javax.swing.JTextArea descriptionTextArea; + javax.swing.JTextArea descriptionTextArea; javax.swing.JCheckBox exportCurrentSegment; private javax.swing.Box.Filler filler1; - private javax.swing.JLabel initialSegCountLabel; + javax.swing.JLabel initialSegCountLabel; javax.swing.JSpinner initialSegCountSpinner; javax.swing.JCheckBox insertFuzzyCheckBox; javax.swing.JRadioButton leaveEmptyRadio; @@ -334,6 +339,7 @@ private void radiosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST: javax.swing.JTextField prefixText; javax.swing.JLabel similarityLabel; javax.swing.JSpinner similaritySpinner; + javax.swing.JCheckBox singleClickActivationCheckBox; javax.swing.JCheckBox stopOnAlternativeTranslation; javax.swing.JCheckBox tagValidateOnLeave; // End of variables declaration//GEN-END:variables diff --git a/src/org/omegat/util/Preferences.java b/src/org/omegat/util/Preferences.java index 42337926f0..ff0ef8b3dd 100644 --- a/src/org/omegat/util/Preferences.java +++ b/src/org/omegat/util/Preferences.java @@ -231,6 +231,11 @@ public final class Preferences { public static final String BEST_MATCH_EXPLANATORY_TEXT = "wf_explanatoryText"; /** Workflow Option: Export current segment */ public static final String EXPORT_CURRENT_SEGMENT = "wf_exportCurrentSegment"; + + /** Editor Option: When activated, a single mouse click activates a segment + * in addition to the usual double click) */ + public static final String SINGLE_CLICK_SEGMENT_ACTIVATION = "wf_singleClickSegmentActivation"; + /** * Workflow Option: Go To Next Untranslated Segment stops when there is at * least one alternative translation diff --git a/test/data/preferences/omegat.prefs.xml b/test/data/preferences/omegat.prefs.xml index 381c76e682..d88c29aa91 100644 --- a/test/data/preferences/omegat.prefs.xml +++ b/test/data/preferences/omegat.prefs.xml @@ -205,6 +205,7 @@ ${targetText} false true false + false false false false From 4863f2539b24acf8fc985bdce53087a7252429ae Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sun, 9 Jun 2024 14:21:00 +0900 Subject: [PATCH 2/2] fix: add bundle message Signed-off-by: Hiroshi Miura --- src/org/omegat/Bundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/omegat/Bundle.properties b/src/org/omegat/Bundle.properties index 017e3b12aa..166d0096db 100644 --- a/src/org/omegat/Bundle.properties +++ b/src/org/omegat/Bundle.properties @@ -1802,6 +1802,7 @@ WG_SAVE_ORIGIN=Save origin of &translation WG_INITIAL_SEGMENT_LOAD_COUNT=Initial number of loaded segments: WG_INITIAL_SEGMENT_LOAD_COUNT_TOOLTIP=When a single file has more segments than this, additional segments will be loaded on-demand as you scroll. WG_PARA_MARK=Paragraph delimiter: +WF_OPTION_ALLOW_SELECT_SINGLE_CLICK=Activate segment with single click (Feature is only active while the cursor is locked.) # org.omegat.gui.preferences.view.TMMatchesPreferencesPanel.java EXT_TMX_DESCRIPTION=Settings for tags originating from non-OmegaT TMX files: