Revision 3102

View differences:

org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/test/java/org/gvsig/tools/AppTest.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.tools;
25

  
26
import junit.framework.Test;
27
import junit.framework.TestCase;
28
import junit.framework.TestSuite;
29

  
30
/**
31
 * Unit test for simple App.
32
 */
33
public class AppTest extends TestCase {
34

  
35
    /**
36
     * @return the suite of tests being tested
37
     */
38
    public static Test suite() {
39
        return new TestSuite(AppTest.class);
40
    }
41

  
42
    /**
43
     * Create the test case
44
     * 
45
     * @param testName
46
     *            name of the test case
47
     */
48
    public AppTest(String testName) {
49
        super(testName);
50
    }
51

  
52
    /**
53
     * Rigourous Test :-)
54
     */
55
    public void testApp() {
56
        assertTrue(true);
57
    }
58
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/texteditor/AbstractJTextEditor.java
1
package org.gvsig.texteditor;
2

  
3
import java.awt.Container;
4
import java.awt.Point;
5
import java.awt.Rectangle;
6
import java.awt.event.ActionEvent;
7
import java.awt.event.ActionListener;
8
import javax.swing.JComponent;
9
import javax.swing.JPanel;
10
import javax.swing.JViewport;
11
import javax.swing.SwingUtilities;
12
import javax.swing.event.CaretEvent;
13
import javax.swing.event.ChangeEvent;
14
import javax.swing.event.ChangeListener;
15
import javax.swing.event.DocumentEvent;
16
import javax.swing.event.DocumentListener;
17
import javax.swing.text.BadLocationException;
18
import javax.swing.text.Document;
19
import javax.swing.text.Element;
20
import javax.swing.text.JTextComponent;
21
import org.gvsig.tools.swing.api.ChangeListenerHelper;
22
import org.gvsig.tools.swing.api.ToolsSwingLocator;
23
import org.gvsig.tools.swing.api.viewer.AbstractJViewer;
24
import org.slf4j.Logger;
25
import org.slf4j.LoggerFactory;
26

  
27
/**
28
 *
29
 * @author jjdelcerro
30
 */
31
public abstract class AbstractJTextEditor extends AbstractJViewer implements JTextEditor {
32
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultJTextEditor.class);
33

  
34
    protected static class UpdateCaretPositionActionEventImpl 
35
                extends ActionEvent 
36
                implements UpdateCaretPositionActionEvent 
37
        {
38

  
39
        private final int line;
40
        private final int column;
41
        private final boolean hasLineAndCol;
42
        
43
        public UpdateCaretPositionActionEventImpl(Object comp, int line, int column, boolean hasLineAndCol) {
44
            super(comp, 1, "UpdateCaretPosition");
45
            this.line = line;
46
            this.column = column;
47
            this.hasLineAndCol = hasLineAndCol;
48
        }
49
        
50
        @Override
51
        public int getLine() {
52
            return this.line;
53
        }
54

  
55
        @Override
56
        public int getColumn() {
57
            return this.column;
58
        }
59

  
60
        @Override
61
        public boolean hasLineAndColumn() {
62
            return this.hasLineAndCol;
63
        }
64
        
65
    }
66
    
67
    protected JPanel panel;
68
    protected ChangeListenerHelper changeListeners;
69
    protected ActionListener updateCaretPositionListener;
70

  
71
    public AbstractJTextEditor(TextEditorManager factory) {
72
        super(factory);
73
        this.panel = new JPanel();
74
        this.changeListeners = ToolsSwingLocator.getToolsSwingManager().createChangeListenerHelper();
75

  
76
        final JTextComponent textComponent = this.getJTextComponent();
77
        final Document textDocument = textComponent.getDocument();
78
        textDocument.addDocumentListener(new DocumentListener() {
79
            @Override
80
            public void insertUpdate(DocumentEvent e) {
81
                changeListeners.fireEvent(new ChangeEvent(AbstractJTextEditor.this));
82
            }
83

  
84
            @Override
85
            public void removeUpdate(DocumentEvent e) {
86
                changeListeners.fireEvent(new ChangeEvent(AbstractJTextEditor.this));
87
            }
88

  
89
            @Override
90
            public void changedUpdate(DocumentEvent e) {
91
                changeListeners.fireEvent(new ChangeEvent(AbstractJTextEditor.this));
92
            }
93
        });
94

  
95
        textComponent.addCaretListener((CaretEvent e) -> {
96
            if (updateCaretPositionListener == null) {
97
                return;
98
            }
99
            int lineNumber = 1;
100
            int columnNumber = 0;
101
            int currentPosition = textComponent.getCaretPosition();
102
            try {
103
                String strText = textDocument.getText(0, currentPosition);
104
                char arrText[] = strText.toCharArray();
105
                for (int i = 0; i < strText.length(); i++) {
106
                    if (arrText[i] == '\n') {
107
                        lineNumber++;
108
                    }
109
                }
110
                columnNumber = currentPosition - strText.lastIndexOf('\n');
111
            } catch (BadLocationException ble) {
112
                System.err.println(ble);
113
            }
114
            updateCaretPositionListener.actionPerformed(
115
                    new UpdateCaretPositionActionEventImpl(
116
                            this, lineNumber, columnNumber, true
117
                    )
118
            );
119
        });
120

  
121
    }
122

  
123
    @Override
124
    public JComponent asJComponent() {
125
        return this.panel;
126
    }
127

  
128
    @Override
129
    public void addChangeListener(ChangeListener listener) {
130
        this.changeListeners.addChangeListener(listener);
131
    }
132

  
133
    @Override
134
    public ChangeListener[] getChangeListeners() {
135
        return this.changeListeners.getChangeListeners();
136
    }
137

  
138
    @Override
139
    public void removeChangeListener(ChangeListener listener) {
140
        this.changeListeners.removeChangeListener(listener);
141
    }
142

  
143
    @Override
144
    public void removeAllChangeListener() {
145
        this.changeListeners.removeAllChangeListener();
146
    }
147

  
148
    @Override
149
    public boolean hasChangeListeners() {
150
        return this.changeListeners.hasChangeListeners();
151
    }
152

  
153
    @Override
154
    public void selectLine(int line) {
155
        JTextComponent editor = this.getJTextComponent();
156
        editor.requestFocusInWindow();
157
        String code = editor.getText();
158
        int lineCounter = 0;
159
        int initialSelection = 0;
160
        int finalSelection = 0;
161
        for (int j = 0; j < code.length(); j++) {
162
            if (code.charAt(j) == '\n') {
163
                lineCounter++;
164
                if (lineCounter == line - 1) {
165
                    initialSelection = j;
166
                }
167
                if (lineCounter == line || (finalSelection == 0 && j == code.length() - 1)) {
168
                    finalSelection = j;
169
                }
170
            }
171
        }
172
        editor.select(initialSelection, finalSelection);
173
    }
174

  
175
    @Override
176
    public void gotoline(int line) {
177
        JTextComponent component = getJTextComponent();
178
        Element root = component.getDocument().getDefaultRootElement();
179
        int lineno = Math.max(line, 1);
180
        int maxlines = root.getElementCount();
181
        lineno = Math.min(lineno, maxlines);
182
        int startOfLineOffset = root.getElement(lineno - 1).getStartOffset();
183
        component.setCaretPosition(startOfLineOffset);
184
        Container container = SwingUtilities.getAncestorOfClass(JViewport.class, component);
185
        if (container == null) {
186
            return;
187
        }
188
        int y = -1;
189
        try {
190
            Rectangle r = component.modelToView(component.getCaretPosition());
191
            JViewport viewport = (JViewport) container;
192
            int extentHeight = viewport.getExtentSize().height;
193
            int viewHeight = viewport.getViewSize().height;
194
            y = Math.max(0, r.y - ((extentHeight - r.height) / 2));
195
            y = Math.min(y, viewHeight - extentHeight);
196
            viewport.setViewPosition(new Point(0, y));
197
        } catch (BadLocationException ble) {
198
            LOGGER.warn("Can't set view position (y=" + y + ").", ble);
199
        }
200
        try {
201
            component.setCaretPosition(startOfLineOffset + 1);
202
        } catch (Exception e) {
203
            LOGGER.warn("Can't set caret position (position=" + (startOfLineOffset + 1) + ").", e);
204
        }
205
    }
206

  
207
    @Override
208
    public int getLineCount() {
209
        JTextComponent textComponent = this.getJTextComponent();
210
        Element map = textComponent.getDocument().getDefaultRootElement();
211
        return map.getElementCount();
212
    }
213

  
214
    @Override
215
    public void addUpdateCaretPositionActionListener(ActionListener listener) {
216
        this.updateCaretPositionListener = listener;
217
    }
218

  
219
    @Override
220
    public boolean isModified() {
221
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
222
    }
223
    
224
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/texteditor/DefaultJTextEditor.java
1
package org.gvsig.texteditor;
2

  
3
import java.awt.BorderLayout;
4
import java.awt.Font;
5
import java.awt.event.ActionEvent;
6
import java.awt.event.ActionListener;
7
import java.io.File;
8
import java.io.IOException;
9
import java.nio.charset.StandardCharsets;
10
import java.util.Objects;
11
import javax.swing.JFileChooser;
12
import javax.swing.JMenu;
13
import javax.swing.JMenuBar;
14
import javax.swing.JMenuItem;
15
import javax.swing.JOptionPane;
16
import javax.swing.JScrollPane;
17
import javax.swing.JTextArea;
18
import javax.swing.event.UndoableEditEvent;
19
import javax.swing.text.JTextComponent;
20
import javax.swing.undo.CannotUndoException;
21
import javax.swing.undo.UndoManager;
22
import org.apache.commons.io.FileUtils;
23

  
24
/**
25
 *
26
 * @author gvSIG Team
27
 */
28
public class DefaultJTextEditor extends AbstractJTextEditor {
29

  
30
    private JTextArea textArea;
31

  
32
    // Is File Saved/Opened
33
    private boolean opened = false;
34
    private boolean saved = false;
35

  
36
    private File openedFile;
37

  
38
    // Undo manager for managing the storage of the undos
39
    // so that the can be redone if requested
40
    private UndoManager undo;
41
    private String mimeType;
42

  
43

  
44
    @SuppressWarnings("OverridableMethodCallInConstructor")
45
    public DefaultJTextEditor(TextEditorManager factory) {
46
        super(factory);
47
        
48
        JMenuBar menuBar = new JMenuBar();
49
        JMenu fileMenu = new JMenu("File");
50
        addMenuItem(fileMenu, "Open...", (ActionEvent e) -> {
51
            doOpenFile();
52
        });
53
        addMenuItem(fileMenu, "Save", (ActionEvent e) -> {
54
            doSaveFile();
55
        });
56
        addMenuItem(fileMenu, "Save as...", (ActionEvent e) -> {
57
            doSaveAsFile();
58
        });
59
        addMenuItem(fileMenu, "Close", (ActionEvent e) -> {
60
            doClose();
61
        });
62

  
63
        JMenu editMenu = new JMenu("Edit");
64
        addMenuItem(editMenu, "Undo", (ActionEvent e) -> {
65
            doUndo();
66
        });
67
        addMenuItem(editMenu, "Redo", (ActionEvent e) -> {
68
            doRedo();
69
        });
70
        addMenuItem(editMenu, "Select all", (ActionEvent e) -> {
71
            doSelectAll();
72
        });
73
        addMenuItem(editMenu, "Cut", (ActionEvent e) -> {
74
            doCut();
75
        });
76
        addMenuItem(editMenu, "Copy", (ActionEvent e) -> {
77
            doCopy();
78
        });
79
        addMenuItem(editMenu, "Paste", (ActionEvent e) -> {
80
            doPaste();
81
        });
82
        menuBar.add(fileMenu);
83
        menuBar.add(editMenu);
84

  
85
        undo = new UndoManager();
86
        textArea.getDocument().addUndoableEditListener((UndoableEditEvent e) -> {
87
            undo.addEdit(e.getEdit());
88
        });
89

  
90
        this.panel.setLayout(new BorderLayout());
91
        this.panel.add(menuBar, BorderLayout.NORTH);
92

  
93
        JScrollPane scroll = new JScrollPane(
94
                getJTextComponent(), 
95
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
96
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
97
        );
98
        this.panel.add(scroll, BorderLayout.CENTER);
99

  
100
    }
101

  
102
    private void addMenuItem(JMenu menu, String text, ActionListener listener) {
103
        JMenuItem item = new JMenuItem(text);
104
        item.addActionListener(listener);
105
        item.setEnabled(true);
106
        menu.add(item);
107
    }
108

  
109
    private void saveFile(File file) {
110
        try {
111
            FileUtils.write(file, textArea.getText());
112
            saved = true;
113
        } catch (IOException ex) {
114
            LOGGER.warn("Can't save file (" + Objects.toString(file) + ")", ex);
115
        }
116
    }
117

  
118
    private void doOpenFile() {
119
        JFileChooser open = new JFileChooser();
120
        open.showOpenDialog(null);
121
        File file = open.getSelectedFile();
122
        try {
123
            openedFile = file;
124
            String s = FileUtils.readFileToString(file);
125
            textArea.setText(s);
126
            opened = true;
127
        } catch (IOException ex) {
128
            LOGGER.warn("Can't open file (" + Objects.toString(file) + ")", ex);
129
        }
130
    }
131

  
132
    private void doSaveFile() {
133
        JFileChooser save = new JFileChooser();
134
        File file = save.getSelectedFile();
135
        if (opened == false && saved == false) {
136
            save.showSaveDialog(null);
137
            int confirmationResult;
138
            if (file.exists()) {
139
                confirmationResult = JOptionPane.showConfirmDialog(this.panel, "Replace existing file?");
140
                if (confirmationResult == JOptionPane.YES_OPTION) {
141
                    saveFile(file);
142
                }
143
            } else {
144
                saveFile(file);
145
            }
146
        } else {
147
            try {
148
                FileUtils.write(openedFile, textArea.getText());
149
            } catch (IOException ex) {
150
                LOGGER.warn("Can't save file (" + Objects.toString(file) + ")", ex);
151
            }
152
        }
153
    }
154

  
155
    private void doSaveAsFile() {
156
        JFileChooser saveAs = new JFileChooser();
157
        saveAs.showSaveDialog(null);
158
        File filename = saveAs.getSelectedFile();
159
        int confirmationResult;
160
        if (filename.exists()) {
161
            confirmationResult = JOptionPane.showConfirmDialog(this.panel, "Replace existing file?");
162
            if (confirmationResult == JOptionPane.YES_OPTION) {
163
                saveFile(filename);
164
            }
165
        } else {
166
            saveFile(filename);
167
        }
168
    }
169

  
170
    private void doClose() {
171
        this.panel.setVisible(false);
172
    }
173

  
174
    private void doUndo() {
175
        try {
176
            undo.undo();
177
        } catch (CannotUndoException ex) {
178
            LOGGER.warn("Can't undo", ex);
179
        }
180
    }
181

  
182
    private void doRedo() {
183
        try {
184
            undo.redo();
185
        } catch (CannotUndoException ex) {
186
            LOGGER.warn("Can't redo", ex);
187
        }
188
    }
189

  
190
    private void doSelectAll() {
191
        textArea.selectAll();
192
    }
193

  
194
    private void doCopy() {
195
        textArea.copy();
196
    }
197

  
198
    private void doPaste() {
199
        textArea.paste();
200
    }
201

  
202
    private void doCut() {
203
        textArea.cut();
204
    }
205

  
206
    @Override
207
    public void setMimetype(String mimeType) {
208
        this.mimeType = mimeType;
209
    }
210

  
211
    @Override
212
    public String getMimetype() {
213
        return this.mimeType;
214
    }
215

  
216
    @Override
217
    public void setContents(Object data) {
218
        if( data instanceof String ) {
219
            this.textArea.setText((String) data);
220
            return;
221
        }
222
        if( data instanceof byte[] ) {
223
            this.textArea.setText(new String((byte[]) data));
224
            return;
225
        }
226
        super.setContents(data);
227
    }
228

  
229
    @Override
230
    public byte[] getBytes() {
231
        return this.textArea.getText().getBytes(StandardCharsets.UTF_8);
232
    }
233

  
234
    @Override
235
    public String getContents() {
236
        return this.textArea.getText();
237
    }
238

  
239

  
240
    @Override
241
    public void clean() {
242
        this.setContents("");
243
    }
244

  
245
    @Override
246
    public JTextComponent getJTextComponent() {
247
        if (this.textArea == null) {
248
            textArea = new JTextArea(30, 50);
249
            textArea.setEditable(true);
250

  
251
            Font textFont = new Font("Verdana", 0, 14);
252
            textArea.setFont(textFont);
253

  
254
        }
255
        return this.textArea;
256
    }
257

  
258
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/texteditor/DefaultTextEditorManager.java
1
package org.gvsig.texteditor;
2

  
3
import org.gvsig.tools.swing.api.viewer.AbstractViewerFactory;
4

  
5

  
6
public class DefaultTextEditorManager extends AbstractViewerFactory implements TextEditorManager {
7

  
8
    public DefaultTextEditorManager() {
9
        super("TextEditor", "Text", "text/plain", true);
10
    }
11
    
12
    @Override
13
    public JTextEditor createTextEditor() {
14
        DefaultJTextEditor editor = new DefaultJTextEditor(this);
15
        return editor;
16
    }
17

  
18
    @Override
19
    public boolean isApplicable(Object... args) {
20
        Object data = args[0];
21
        return data instanceof String || data instanceof byte[];
22
    }
23
    
24
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/tools/swing/impl/hexeditor/HexEditorFactory.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2023 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.tools.swing.impl.hexeditor;
25

  
26
import java.io.InputStream;
27
import org.gvsig.tools.swing.api.viewer.AbstractViewerFactory;
28
import org.gvsig.tools.swing.api.viewer.JViewer;
29

  
30
/**
31
 *
32
 * @author jjdelcerro
33
 * @param <T>
34
 */
35
public class HexEditorFactory<T> extends AbstractViewerFactory<T> {
36

  
37
    public HexEditorFactory() {
38
        super("HexEditor", "Hexadecimal", "application/octet-stream", false);
39
    }
40
    
41
    @Override
42
    public JViewer<T> createViewer() {
43
        return new HexEditor(this);
44
    }
45

  
46
    @Override
47
    public boolean isApplicable(Object... args) {
48
        Object data = args[0];
49
        if( data instanceof byte[] ) {
50
            return true;
51
        }
52
        if( data instanceof String ) {
53
            return true;
54
        }
55
        if( data instanceof InputStream ) {
56
            return true;
57
        }
58
        return false;
59
    }
60
    
61
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/tools/swing/impl/hexeditor/swing/ByteArrayTransferable.java
1
package org.gvsig.tools.swing.impl.hexeditor.swing;
2

  
3
import java.awt.datatransfer.DataFlavor;
4
import java.awt.datatransfer.Transferable;
5
import java.awt.datatransfer.UnsupportedFlavorException;
6
import java.io.IOException;
7
import java.io.StringReader;
8

  
9

  
10
/*
11
 * Based on portions of code from ajaxproxy in GitHub
12
 * Copyright (c) 2008 Robert Futrell
13
 * https://github.com/mdeanda/ajaxproxy/tree/master/src/main/java/org/fife/ui/hex
14
 */
15
 
16
class ByteArrayTransferable implements Transferable {
17

  
18
	private int offset;
19
	private byte[] bytes;
20

  
21
	private static final DataFlavor[] FLAVORS = {
22
		DataFlavor.stringFlavor,
23
		DataFlavor.plainTextFlavor,
24
	};
25

  
26

  
27
	/**
28
	 * Creates a transferable object.
29
	 *
30
	 * @param bytes The bytes to transfer.
31
	 */
32
	public ByteArrayTransferable(int offset, byte[] bytes) {
33
		this.offset = offset;
34
		if (bytes!=null) {
35
			this.bytes = (byte[])bytes.clone();
36
		}
37
		else {
38
			this.bytes = new byte[0];
39
		}
40
	}
41

  
42

  
43
	/**
44
	 * Returns the number of bytes being transferred.
45
	 *
46
	 * @return The number of bytes being transferred.
47
	 * @see #getOffset()
48
	 */
49
	public int getLength() {
50
		return bytes.length;
51
	}
52

  
53

  
54
	/**
55
	 * Returns the offset of the first byte being transferred.
56
	 *
57
	 * @return The offset of the first byte.
58
	 * @see #getLength()
59
	 */
60
	public int getOffset() {
61
		return offset;
62
	}
63

  
64

  
65
	/**
66
	 * Returns the data being transferred in a format specified by the
67
	 * <code>DataFlavor</code>.
68
	 *
69
	 * @param flavor Dictates in what format the data should be returned.
70
	 * @throws UnsupportedFlavorException If the specified flavor is not
71
	 *         supported.
72
	 * @throws IOException If an IO error occurs.
73
	 * @see DataFlavor#getRepresentationClass()
74
	 */
75
	public Object getTransferData(DataFlavor flavor)
76
			throws UnsupportedFlavorException, IOException {
77
		if (flavor.equals(FLAVORS[0])) {
78
			return new String(bytes); // Use platform default charset.
79
		}
80
		else if (flavor.equals(FLAVORS[1])) {
81
			return new StringReader(new String(bytes));
82
		}
83
	    throw new UnsupportedFlavorException(flavor);
84
	}
85

  
86

  
87
	/**
88
	 * Returns an array of DataFlavor objects indicating the flavors the data 
89
	 * can be provided in.  The array is ordered according to preference for 
90
	 * providing the data (from most richly descriptive to least descriptive).
91
	 *
92
	 * @return An array of data flavors in which this data can be transferred.
93
	 */
94
	public DataFlavor[] getTransferDataFlavors() {
95
		return (DataFlavor[])FLAVORS.clone();
96
	}
97

  
98

  
99
	/**
100
	 * Returns whether a data flavor is supported.
101
	 *
102
	 * @param flavor The flavor to check.
103
	 * @return Whether the specified flavor is supported.
104
	 */
105
	public boolean isDataFlavorSupported(DataFlavor flavor) {
106
		for (int i=0; i<FLAVORS.length; i++) {
107
			if (flavor.equals(FLAVORS[i])) {
108
				return true;
109
			}
110
		}
111
		return false;
112
	}
113

  
114

  
115
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/tools/swing/impl/hexeditor/swing/HexEditorRowHeader.java
1
package org.gvsig.tools.swing.impl.hexeditor.swing;
2

  
3
import java.awt.Component;
4
import java.awt.Graphics;
5
import javax.swing.AbstractListModel;
6
import javax.swing.BorderFactory;
7
import javax.swing.DefaultListCellRenderer;
8
import javax.swing.JLabel;
9
import javax.swing.JList;
10
import javax.swing.ListSelectionModel;
11

  
12

  
13
import javax.swing.border.EmptyBorder;
14
import javax.swing.border.Border;
15
import javax.swing.event.TableModelEvent;
16
import javax.swing.event.TableModelListener;
17

  
18
/*
19
 * Based on portions of code from ajaxproxy in GitHub
20
 * Copyright (c) 2008 Robert Futrell
21
 * https://github.com/mdeanda/ajaxproxy/tree/master/src/main/java/org/fife/ui/hex
22
 */
23
 
24

  
25
/**
26
 * Header of the hex table; displays address of the first byte on the
27
 * row.
28
 */
29
class HexEditorRowHeader extends JList implements TableModelListener {
30

  
31
	private static final long serialVersionUID = 1L;
32

  
33
	private HexTable table;
34
	private RowHeaderListModel model;
35

  
36
	private static final Border CELL_BORDER =
37
							BorderFactory.createEmptyBorder(0,5,0,5);
38

  
39

  
40
	/**
41
	 * Constructor.
42
	 *
43
	 * @param table The table displaying the hex content.
44
	 */
45
	public HexEditorRowHeader(HexTable table) {
46
		this.table = table;
47
		model = new RowHeaderListModel();
48
		setModel(model);
49
		setFocusable(false);
50
		setFont(table.getFont());
51
		setFixedCellHeight(table.getRowHeight());
52
		setCellRenderer(new CellRenderer());
53
		setBorder(new RowHeaderBorder());
54
		setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
55
		syncRowCount(); // Initialize to initial size of table.
56
		table.getModel().addTableModelListener(this);
57
	}
58

  
59

  
60
	public void addSelectionInterval(int anchor, int lead) {
61
		super.addSelectionInterval(anchor, lead);
62
		int min = Math.min(anchor, lead);
63
		int max = Math.max(anchor, lead);
64
		table.setSelectedRows(min, max);
65
	}
66

  
67

  
68
	public void removeSelectionInterval(int index0, int index1) {
69
		super.removeSelectionInterval(index0, index1);
70
		int anchor = getAnchorSelectionIndex();
71
		int lead = getLeadSelectionIndex();
72
		table.setSelectedRows(Math.min(anchor, lead), Math.max(anchor, lead));
73
	}
74

  
75

  
76
	public void setSelectionInterval(int anchor, int lead) {
77
		super.setSelectionInterval(anchor, lead);
78
		int min = Math.min(anchor, lead);
79
		int max = Math.max(anchor, lead);
80
		// Table may be showing 0 bytes, but we're showing 1 row header
81
		if (max<table.getRowCount()) {
82
			table.setSelectedRows(min, max);
83
		}
84
	}
85

  
86

  
87
	private void syncRowCount() {
88
		if (table.getRowCount()!=model.getSize()) {
89
			// Always keep 1 row, even if showing 0 bytes in editor
90
			model.setSize(Math.max(1, table.getRowCount()));
91
		}
92
	}
93

  
94

  
95
	public void tableChanged(TableModelEvent e) {
96
		syncRowCount();
97
	}
98

  
99

  
100
	/**
101
	 * Renders the cells of the row header.
102
	 *
103
	 * @author Robert Futrell
104
	 * @version 1.0
105
	 */
106
	private class CellRenderer extends DefaultListCellRenderer {
107

  
108
		private static final long serialVersionUID = 1L;
109

  
110
		public CellRenderer() {
111
			setHorizontalAlignment(JLabel.RIGHT);
112
		}
113

  
114
		public Component getListCellRendererComponent(JList list, Object value,
115
							int index, boolean selected, boolean hasFocus) {
116
			// Never paint cells as "selected."
117
			super.getListCellRendererComponent(list, value, index,
118
												false, hasFocus);
119
			setBorder(CELL_BORDER);
120
//			setBackground(table.getBackground());
121
			return this;
122
		}
123

  
124
	}
125

  
126

  
127
	/**
128
	 * List model used by the header for the hex table.
129
	 *
130
	 * @author Robert Futrell
131
	 * @version 1.0
132
	 */
133
	private static class RowHeaderListModel extends AbstractListModel {
134

  
135
		private static final long serialVersionUID = 1L;
136

  
137
		private int size;
138

  
139
		public Object getElementAt(int index) {
140
			return "0x" + Integer.toHexString(index*16);
141
		}
142

  
143
		public int getSize() {
144
			return size;
145
		}
146

  
147
		public void setSize(int size) {
148
			int old = this.size;
149
			this.size = size;
150
			int diff = size - old;
151
			if (diff>0) {
152
				fireIntervalAdded(this, old, size-1);
153
			}
154
			else if (diff<0) {
155
				fireIntervalRemoved(this, size+1, old-1);
156
			}
157
		}
158

  
159
	}
160

  
161

  
162
	/**
163
	 * Border for the entire row header.  This draws a line to separate the
164
	 * header from the table contents, and gives a small amount of whitespace
165
	 * to separate the two.
166
	 *
167
	 * @author Robert Futrell
168
	 * @version 1.0
169
	 */
170
	private class RowHeaderBorder extends EmptyBorder {
171

  
172
		private static final long serialVersionUID = 1L;
173

  
174
		public RowHeaderBorder() {
175
			super(0,0,0,2);
176
		}
177

  
178
	    public void paintBorder(Component c, Graphics g, int x, int y,
179
	    						int width, int height) {
180
	    	x = x + width - this.right;
181
//	    	g.setColor(table.getBackground());
182
//	    	g.fillRect(x,y, width,height);
183
	    	g.setColor(table.getGridColor());
184
	    	g.drawLine(x,y, x,y+height);
185
	    }
186

  
187
	}
188

  
189

  
190
}
org.gvsig.tools/library/tags/org.gvsig.tools-3.0.376/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/tools/swing/impl/hexeditor/swing/HexTable.java
1
package org.gvsig.tools.swing.impl.hexeditor.swing;
2

  
3
import java.awt.AWTEvent;
4
import java.awt.Color;
5
import java.awt.Component;
6
import java.awt.Dimension;
7
import java.awt.Font;
8
import java.awt.FontMetrics;
9
import java.awt.Graphics;
10
import java.awt.Graphics2D;
11
import java.awt.Point;
12
import java.awt.Rectangle;
13
import java.awt.event.FocusEvent;
14
import java.awt.event.FocusListener;
15
import java.awt.event.KeyEvent;
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.util.Map;
19
import javax.swing.DefaultCellEditor;
20
import javax.swing.JTable;
21
import javax.swing.JTextField;
22
import javax.swing.ListSelectionModel;
23
import javax.swing.UIManager;
24
import javax.swing.table.DefaultTableCellRenderer;
25
import javax.swing.table.TableCellRenderer;
26
import javax.swing.table.TableColumn;
27
import javax.swing.text.AbstractDocument;
28
import javax.swing.text.AttributeSet;
29
import javax.swing.text.BadLocationException;
30
import javax.swing.text.Document;
31
import javax.swing.text.DocumentFilter;
32
import javax.swing.text.JTextComponent;
33
import org.gvsig.tools.swing.impl.hexeditor.event.SelectionChangedEvent;
34
import org.gvsig.tools.swing.impl.hexeditor.event.SelectionChangedListener;
35

  
36

  
37

  
38
/*
39
 * Based on portions of code from ajaxproxy in GitHub
40
 * Copyright (c) 2008 Robert Futrell
41
 * https://github.com/mdeanda/ajaxproxy/tree/master/src/main/java/org/fife/ui/hex
42
 */
43
 
44

  
45
/**
46
 * The table displaying the hex content of a file.  This is the meat of
47
 * the hex viewer.
48
 *
49
 */
50
class HexTable extends JTable {
51

  
52
	private static final long serialVersionUID = 1L;
53

  
54
	private final HexEditorComponent hexEditor;
55
	private HexTableModel model;
56
	int leadSelectionIndex;
57
	int anchorSelectionIndex;
58

  
59
	private static final Color ANTERNATING_CELL_COLOR = new Color(240,240,240);
60

  
61
	private CellEditor cellEditor = new CellEditor();
62

  
63
	/**
64
	 * Creates a new table to display hex data.
65
	 *
66
	 * @param hexEditor The parent hex editor component.
67
	 * @param model The table model to use.
68
	 */
69
	public HexTable(HexEditorComponent hexEditor, HexTableModel model) {
70

  
71
		super(model);
72
		this.hexEditor = hexEditor;
73
		this.model = model;
74
		enableEvents(AWTEvent.KEY_EVENT_MASK);
75
		setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
76
		setFont(new Font("Monospaced", Font.PLAIN, 14));
77
//setRowHeight(28);
78
		setCellSelectionEnabled(true);
79
		setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
80
		setDefaultEditor(Object.class, cellEditor);
81
		setDefaultRenderer(Object.class, new CellRenderer());
82
		getTableHeader().setReorderingAllowed(false);
83
		setShowGrid(false);
84

  
85
		FontMetrics fm = getFontMetrics(getFont());
86
		Font headerFont = UIManager.getFont("TableHeader.font");
87
		FontMetrics headerFM = hexEditor.getFontMetrics(headerFont);
88
		int w = fm.stringWidth("www"); // cell contents, 0-255
89
		w = Math.max(w, headerFM.stringWidth("+99"));
90
		for (int i=0; i<getColumnCount(); i++) {
91
			TableColumn column = getColumnModel().getColumn(i);
92
			if (i<16) {
93
				column.setPreferredWidth(w);
94
			}
95
			else {
96
				column.setPreferredWidth(HexEditorComponent.DUMP_COLUMN_WIDTH);
97
			}
98
		}
99

  
100
		setPreferredScrollableViewportSize(
101
				new Dimension(w*16+HexEditorComponent.DUMP_COLUMN_WIDTH, 25*getRowHeight()));
102

  
103
		anchorSelectionIndex = leadSelectionIndex = 0;
104

  
105
	}
106

  
107

  
108
	/**
109
	 * Registers a prospect who is interested when the text selection from the
110
	 * hex editor becomes changed.
111
	 * 
112
	 * @param l The concerning listener.
113
	 * @see #removeSelectionChangedListener(SelectionChangedListener)
114
	 */
115
	public void addSelectionChangedListener(SelectionChangedListener l) {
116
		listenerList.add(SelectionChangedListener.class, l);
117
	}
118

  
119

  
120
	/**
121
	 * Returns the column for the cell containing data that is the closest
122
	 * to the specified cell.  This is used when, for example, the user clicks
123
	 * on an "empty" cell in the last row of the table.
124
	 *  
125
	 * @param row The row of the cell clicked on.
126
	 * @param col The column of the cell clicked on.
127
	 * @return The column of the closest cell containing data.
128
	 */
129
	private int adjustColumn(int row, int col) {
130
		if (col<0) {
131
			return 0;
132
		}
133
		if (row==getRowCount()-1) {
134
			int lastRowCount = model.getByteCount()%16;
135
			if (lastRowCount==0) {
136
				lastRowCount = 16;
137
			}
138
			if (lastRowCount<16) { // Last row's not entirely full
139
				return Math.min(col, (model.getByteCount()%16)-1);
140
			}
141
		}
142
		return Math.min(col, getColumnCount()-1-1);
143
	}
144

  
145

  
146
	/**
147
	 * Returns the offset into the bytes being edited represented at the
148
	 * specified cell in the table, if any.
149
	 *
150
	 * @param row The row in the table.
151
	 * @param col The column in the table.
152
	 * @return The offset into the byte array, or <code>-1</code> if the
153
	 *         cell does not represent part of the byte array (such as the
154
	 *         tailing "ascii dump" column's cells).
155
	 * @see #offsetToCell(int)
156
	 */
157
	public int cellToOffset(int row, int col) {
158
		// Check row and column individually to prevent them being invalid
159
		// values but still pointing to a valid offset in the buffer.
160
		if (row<0 || row>=getRowCount() ||
161
				col<0 || col>15) { // Don't include last column (ascii dump)
162
			return -1;
163
		}
164
		int offs = row*16 + col;
165
		return (offs>=0 && offs<model.getByteCount()) ? offs : -1;
166
	}
167

  
168

  
169
	/**
170
	 * Changes the selected byte range.
171
	 *
172
	 * @param row
173
	 * @param col
174
	 * @param toggle
175
	 * @param extend
176
	 * @see #changeSelectionByOffset(int, boolean)
177
	 * @see #setSelectedRows(int, int)
178
	 * @see #setSelectionByOffsets(int, int)
179
	 */
180
	public void changeSelection(int row, int col, boolean toggle,
181
								boolean extend) {
182
	    
183
	    // remind previous selection range
184
		int prevSmallest = getSmallestSelectionIndex();
185
		int prevLargest = getLargestSelectionIndex();
186
	    
187
		// Don't allow the user to select the "ascii dump" or any
188
		// empty cells in the last row of the table.
189
		col = adjustColumn(row, col);
190
		if (row<0) {
191
			row = 0;
192
		}
193

  
194
		// Clear the old selection (may not be necessary).
195
		repaintSelection();
196

  
197
		if (extend) {
198
			leadSelectionIndex = cellToOffset(row, col);
199
		}
200
		else {
201
			anchorSelectionIndex = leadSelectionIndex = cellToOffset(row, col);
202
		}
203

  
204
        // Scroll after changing the selection as blit scrolling is
205
		// immediate, so that if we cause the repaint after the scroll we
206
		// end up painting everything!
207
		if (getAutoscrolls()) {
208
			ensureCellIsVisible(row, col);
209
		}
210

  
211
		// Draw the new selection.
212
		repaintSelection();
213

  
214
		fireSelectionChangedEvent(prevSmallest, prevLargest);
215

  
216
	}
217

  
218

  
219
	/**
220
	 * Changes the selection by an offset into the bytes being edited.
221
	 *
222
	 * @param offset
223
	 * @param extend
224
	 * @see #changeSelection(int, int, boolean, boolean)
225
	 * @see #setSelectedRows(int, int)
226
	 * @see #setSelectionByOffsets(int, int)
227
	 */
228
	public void changeSelectionByOffset(int offset, boolean extend) {
229
		offset = Math.max(0, offset);
230
		offset = Math.min(offset, model.getByteCount()-1);
231
		int row = offset/16;
232
		int col = offset%16;
233
		changeSelection(row, col, false, extend);
234
	}
235

  
236

  
237
	/**
238
	 * Clears the selection.  The "lead" of the selection is set back to the
239
	 * position of the "anchor."
240
	 */
241
	public void clearSelection() {
242
		if (anchorSelectionIndex>-1) { // Always true unless an error
243
			leadSelectionIndex = anchorSelectionIndex;
244
		}
245
		else {
246
			anchorSelectionIndex = leadSelectionIndex = 0;
247
		}
248
		repaintSelection();
249
	}
250

  
251

  
252
	/**
253
	 * Ensures the specified cell is visible.
254
	 *
255
	 * @param row The row of the cell.
256
	 * @param col The column of the cell.
257
	 */
258
	private void ensureCellIsVisible(int row, int col) {
259
		Rectangle cellRect = getCellRect(row, col, false);
260
		if (cellRect != null) {
261
			scrollRectToVisible(cellRect);
262
		}
263
	}
264

  
265

  
266
	/**
267
	 * Notifies any listeners that the selection has changed.
268
	 * 
269
	 * @see #addSelectionChangedListener(SelectionChangedListener)
270
	 * @see #removeSelectionChangedListener(SelectionChangedListener)
271
	 * @param e Contains proper information.
272
	 */
273
	private void fireSelectionChangedEvent(int prevSmallest, int prevLargest) {
274

  
275
		// Lazily create the event
276
		SelectionChangedEvent e = null;
277

  
278
		// Guaranteed non-null array
279
		Object[] listeners = listenerList.getListenerList();
280
		// Process last to first
281
		for (int i=listeners.length-2; i>=0; i-=2) {
282
			if (listeners[i]==SelectionChangedListener.class) {
283
				if (e==null) {
284
				    e = new SelectionChangedEvent(this,
285
				    	prevSmallest, prevLargest,
286
				    	getSmallestSelectionIndex(), getLargestSelectionIndex());
287
				}
288
				((SelectionChangedListener)listeners[i+1]).selectionChanged(e);
289
			}
290
		}
291

  
292
	}
293

  
294

  
295
	/**
296
	 * Returns the byte at the specified offset.
297
	 *
298
	 * @param offset The offset.
299
	 * @return The byte.
300
	 */
301
	public byte getByte(int offset) {
302
		return model.getByte(offset);
303
	}
304

  
305
        public byte[] getBytes() {
306
            return this.model.getBytes();
307
        }
308

  
309
	/**
310
	 * Returns the number of bytes being edited.
311
	 *
312
	 * @return The number of bytes.
313
	 */
314
	public int getByteCount() {
315
		return model.getByteCount();
316
	}
317

  
318

  
319
	/**
320
	 * Returns the rendering hints for text that will most accurately reflect
321
	 * those of the native windowing system.
322
	 *
323
	 * @return The rendering hints, or <code>null</code> if they cannot be
324
	 *         determined.
325
	 */
326
	private Map getDesktopAntiAliasHints() {
327
		return (Map)getToolkit().getDesktopProperty("awt.font.desktophints");
328
	}
329

  
330

  
331
	/**
332
	 * Returns the largest selection index.
333
	 *
334
	 * @return The largest selection index.
335
	 * @see #getSmallestSelectionIndex()
336
	 */
337
	public int getLargestSelectionIndex() {
338
		int index = Math.max(leadSelectionIndex, anchorSelectionIndex);
339
		return Math.max(index, 0); // Don't return -1 if table is empty
340
	}
341

  
342

  
343
	/**
344
	 * Returns the smallest selection index.
345
	 *
346
	 * @return The smallest selection index.
347
	 * @see #getLargestSelectionIndex()
348
	 */
349
	public int getSmallestSelectionIndex() {
350
		int index = Math.min(leadSelectionIndex, anchorSelectionIndex);
351
		return Math.max(index, 0); // Don't return -1 if table is empty
352
	}
353

  
354

  
355
	public boolean isCellEditable(int row, int col) {
356
		return cellToOffset(row, col)>-1;
357
	}
358

  
359

  
360
	public boolean isCellSelected(int row, int col) {
361
		int offset = cellToOffset(row, col);
362
		if (offset==-1) { // "Ascii dump" column
363
			return false;
364
		}
365
		int start = getSmallestSelectionIndex();
366
		int end = getLargestSelectionIndex();
367
		return offset>=start && offset<=end;
368
	}
369

  
370

  
371
	/**
372
	 * Returns the cell representing the specified offset into the hex
373
	 * document.
374
	 *
375
	 * @param offset The offset into the document.
376
	 * @return The cell, in the form <code>(row, col)</code>.  If the
377
	 *         specified offset is invalid, <code>(-1, -1)</code> is returned.
378
	 * @see #cellToOffset(int, int)
379
	 */
380
	public Point offsetToCell(int offset) {
381
		if (offset<0 || offset>=model.getByteCount()) {
382
			return new Point(-1, -1);
383
		}
384
		int row = offset/16;
385
		int col = offset%16;
386
		return new Point(row, col);
387
	}
388

  
389

  
390
	/**
391
	 * Sets the contents in the hex editor to the contents of the specified
392
	 * file.
393
	 *
394
	 * @param fileName The name of the file to open.
395
	 * @throws IOException If an IO error occurs.
396
	 */
397
	public void open(String fileName) throws IOException {
398
		model.setBytes(fileName); // Fires tableDataChanged event
399
	}
400

  
401

  
402
	/**
403
	 * Sets the contents in the hex editor to the contents of the specified
404
	 * input stream.
405
	 *
406
	 * @param in An input stream.
407
	 * @throws IOException If an IO error occurs.
408
	 */
409
	public void open(InputStream in) throws IOException {
410
		model.setBytes(in);
411
	}
412

  
413

  
414
	public Component prepareRenderer(TableCellRenderer renderer, int row,
415
									int column) {
416
		Object value = getValueAt(row, column);
417
		boolean isSelected = isCellSelected(row, column);
418
		boolean hasFocus = cellToOffset(row, column)==leadSelectionIndex;
419

  
420
		return renderer.getTableCellRendererComponent(this, value,
421
										isSelected, hasFocus, row, column);
422
	}
423

  
424

  
425
	protected void processKeyEvent (java.awt.event.KeyEvent e) {
426

  
427
		// TODO: Convert into Actions and put into InputMap/ActionMap?
428
		if (e.getID()==KeyEvent.KEY_PRESSED) {
429
			switch (e.getKeyCode()) {
430
				case KeyEvent.VK_LEFT:
431
					boolean extend = e.isShiftDown();
432
					int offs = Math.max(leadSelectionIndex-1, 0);
433
					changeSelectionByOffset(offs, extend);
434
					e.consume();
435
					break;
436
				case KeyEvent.VK_RIGHT:
437
					extend = e.isShiftDown();
438
					offs = Math.min(leadSelectionIndex+1, model.getByteCount()-1);
439
					changeSelectionByOffset(offs, extend);
440
					e.consume();
441
					break;
442
				case KeyEvent.VK_UP:
443
					extend = e.isShiftDown();
444
					offs = Math.max(leadSelectionIndex-16, 0);
445
					changeSelectionByOffset(offs, extend);
446
					e.consume();
447
					break;
448
				case KeyEvent.VK_DOWN:
449
					extend = e.isShiftDown();
450
					offs = Math.min(leadSelectionIndex+16, model.getByteCount()-1);
451
					changeSelectionByOffset(offs, extend);
452
					e.consume();
453
					break;
454
				case KeyEvent.VK_PAGE_DOWN:
455
					extend = e.isShiftDown();
456
					int visibleRowCount = getVisibleRect().height/getRowHeight();
457
					offs = Math.min(leadSelectionIndex+visibleRowCount*16,
458
									model.getByteCount()-1);
459
					changeSelectionByOffset(offs, extend);
460
					e.consume();
461
					break;
462
				case KeyEvent.VK_PAGE_UP:
463
					extend = e.isShiftDown();
464
					visibleRowCount = getVisibleRect().height/getRowHeight();
465
					offs = Math.max(leadSelectionIndex-visibleRowCount*16, 0);
466
					changeSelectionByOffset(offs, extend);
467
					e.consume();
468
					break;
469
				case KeyEvent.VK_HOME:
470
					extend = e.isShiftDown();
471
					offs = (leadSelectionIndex/16)*16;
472
					changeSelectionByOffset(offs, extend);
473
					e.consume();
474
					break;
475
				case KeyEvent.VK_END:
476
					extend = e.isShiftDown();
477
					offs = (leadSelectionIndex/16)*16 + 15;
478
					offs = Math.min(offs, model.getByteCount()-1);
479
					changeSelectionByOffset(offs, extend);
480
					e.consume();
481
					break;
482
			}
483
		}
484

  
485
		super.processKeyEvent(e);
486

  
487
	}
488

  
489

  
490
	/**
491
	 * Tries to redo the last action undone.
492
	 *
493
	 * @return Whether there is another action to redo after this one.
494
	 * @see #undo()
495
	 */
496
	public boolean redo() {
497
		return model.redo();
498
	}
499

  
500

  
501
	/**
502
	 * Removes a range of bytes.
503
	 *
504
	 * @param offs The offset of the range of bytes to remove.
505
	 * @param len The number of bytes to remove.
506
	 * @see #replaceBytes(int, int, byte[])
507
	 */
508
	void removeBytes(int offs, int len) {
509
		model.removeBytes(offs, len);
510
	}
511

  
512

  
513
	private void repaintSelection() {
514
		// TODO: Repaint only selected lines.
515
		repaint();
516
	}
517
    
518

  
519
	/**
520
	 * Removes a listener who isn't any longer interested whether the text
521
	 * selection from the hex editor becomes changed.
522
	 * 
523
	 * @param l The concerning previous prospect.
524
	 * @see #addSelectionChangedListener(SelectionChangedListener)
525
	 */
526
	public void removeSelectionChangedListener(SelectionChangedListener l) {
527
		listenerList.remove(SelectionChangedListener.class, l);
528
	}
529

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff