Classes in this Package | Line Coverage | Branch Coverage | Complexity | ||||||||
AbstractAction |
|
| 1.9230769230769231;1,923 |
1 | /** |
|
2 | * Redistribution and use in source and binary forms, with or without |
|
3 | * modification, are permitted provided that the following conditions are |
|
4 | * met : |
|
5 | * |
|
6 | * . Redistributions of source code must retain the above copyright |
|
7 | * notice, this list of conditions and the following disclaimer. |
|
8 | * |
|
9 | * . Redistributions in binary form must reproduce the above copyright |
|
10 | * notice, this list of conditions and the following disclaimer in the |
|
11 | * documentation and/or other materials provided with the distribution. |
|
12 | * |
|
13 | * . The name of the author may not be used to endorse or promote products |
|
14 | * derived from this software without specific prior written permission. |
|
15 | * |
|
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
|
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
24 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
25 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 | * POSSIBILITY OF SUCH DAMAGE. |
|
27 | * |
|
28 | * $Id$ |
|
29 | */ |
|
30 | ||
31 | package palmed.edit.selection; |
|
32 | ||
33 | import java.io.ByteArrayInputStream; |
|
34 | import java.io.ByteArrayOutputStream; |
|
35 | import java.io.IOException; |
|
36 | import palmed.util.ChainedException; |
|
37 | ||
38 | /** |
|
39 | * This class factorizes behaviours common to all actions. |
|
40 | * |
|
41 | * @author Mathieu Champlon |
|
42 | * @version $Revision$ $Date$ |
|
43 | */ |
|
44 | public abstract class AbstractAction implements IAction |
|
45 | { |
|
46 | /** |
|
47 | * The selection. |
|
48 | */ |
|
49 | private final ISelection selection_; |
|
50 | /** |
|
51 | * A backup of the initial selection state. |
|
52 | */ |
|
53 | private byte[] initial_; |
|
54 | /** |
|
55 | * A backup of the final selection state. |
|
56 | */ |
|
57 | private byte[] final_; |
|
58 | /** |
|
59 | * A backup of the removed data. |
|
60 | */ |
|
61 | private byte[] data_; |
|
62 | ||
63 | /** |
|
64 | * Create an abstract action. |
|
65 | * |
|
66 | * @param selection the selection |
|
67 | */ |
|
68 | protected AbstractAction( final ISelection selection ) |
|
69 | 540 | { |
70 | 540 | if( selection == null ) |
71 | 0 | throw new IllegalArgumentException( "parameter 'selection' is null" ); |
72 | 540 | selection_ = selection; |
73 | 540 | } |
74 | ||
75 | /** |
|
76 | * {@inheritDoc} |
|
77 | */ |
|
78 | public final void perform() |
|
79 | { |
|
80 | 540 | initial_ = backupState(); |
81 | 540 | onPerform(); |
82 | 540 | final_ = backupState(); |
83 | 540 | } |
84 | ||
85 | /** |
|
86 | * {@inheritDoc} |
|
87 | */ |
|
88 | public final void undo() |
|
89 | { |
|
90 | 110 | restoreState( final_ ); |
91 | 110 | if( onUndo() ) |
92 | 60 | restoreState( initial_ ); |
93 | 110 | } |
94 | ||
95 | /** |
|
96 | * {@inheritDoc} |
|
97 | */ |
|
98 | public final void redo() |
|
99 | { |
|
100 | 50 | restoreState( initial_ ); |
101 | 50 | if( onRedo() ) |
102 | 10 | restoreState( final_ ); |
103 | 50 | } |
104 | ||
105 | /** |
|
106 | * Perform the action. |
|
107 | */ |
|
108 | protected abstract void onPerform(); |
|
109 | ||
110 | /** |
|
111 | * Undo the action. |
|
112 | * |
|
113 | * @return Whether the initial state must be restored or not |
|
114 | */ |
|
115 | protected abstract boolean onUndo(); |
|
116 | ||
117 | /** |
|
118 | * Redo the action. |
|
119 | * |
|
120 | * @return Whether the final state must be restored or not |
|
121 | */ |
|
122 | protected abstract boolean onRedo(); |
|
123 | ||
124 | /** |
|
125 | * Overwrite the current final state with the one of another action. |
|
126 | * |
|
127 | * @param action the action |
|
128 | */ |
|
129 | protected final void overwriteFinalState( final AbstractAction action ) // FIXME dirty |
|
130 | { |
|
131 | 260 | final_ = action.final_; |
132 | 260 | } |
133 | ||
134 | /** |
|
135 | * Prepend the current backup data with the data from another action. |
|
136 | * |
|
137 | * @param action the action |
|
138 | */ |
|
139 | protected final void prependData( final AbstractAction action ) // FIXME dirty |
|
140 | { |
|
141 | 15 | final byte[] data = new byte[data_.length + action.data_.length]; |
142 | 15 | System.arraycopy( action.data_, 0, data, 0, action.data_.length ); |
143 | 15 | System.arraycopy( data_, 0, data, action.data_.length, data_.length ); |
144 | 15 | data_ = data; |
145 | 15 | } |
146 | ||
147 | private byte[] backupState() |
|
148 | { |
|
149 | 1080 | final ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
150 | try |
|
151 | { |
|
152 | 1080 | selection_.marshall( stream ); |
153 | } |
|
154 | 0 | catch( IOException e ) |
155 | { |
|
156 | 0 | throw new ChainedException( e ); // FIXME custom exception |
157 | 1080 | } |
158 | 1080 | return stream.toByteArray(); |
159 | } |
|
160 | ||
161 | private void restoreState( final byte[] state ) |
|
162 | { |
|
163 | try |
|
164 | { |
|
165 | 230 | selection_.unmarshall( new ByteArrayInputStream( state ) ); |
166 | } |
|
167 | 0 | catch( IOException e ) |
168 | { |
|
169 | 0 | throw new ChainedException( e ); // FIXME custom exception |
170 | 230 | } |
171 | 230 | } |
172 | ||
173 | /** |
|
174 | * Backup the selected text. |
|
175 | */ |
|
176 | protected final void backupData() |
|
177 | { |
|
178 | 180 | final ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
179 | try |
|
180 | { |
|
181 | 180 | selection_.write( stream ); |
182 | } |
|
183 | 0 | catch( IOException e ) |
184 | { |
|
185 | 0 | throw new ChainedException( e ); // FIXME custom exception |
186 | 180 | } |
187 | 180 | data_ = stream.toByteArray(); |
188 | 180 | } |
189 | ||
190 | /** |
|
191 | * Remove the selected text and restore backup. |
|
192 | */ |
|
193 | protected final void restoreData() |
|
194 | { |
|
195 | try |
|
196 | { |
|
197 | 95 | selection_.read( new ByteArrayInputStream( data_ ) ); |
198 | } |
|
199 | 0 | catch( IOException e ) |
200 | { |
|
201 | 0 | throw new ChainedException( e ); // FIXME custom exception |
202 | 95 | } |
203 | 95 | } |
204 | } |