Class: Fox::FXUndoList

Inherits:
FXObject show all
Includes:
Responder
Defined in:
lib/fox16/undolist.rb

Overview

The undo list manages a list of undoable (and redoable) commands for a FOX application; it works hand-in-hand with subclasses of FXCommand and is an application of the well-known Command pattern. Your application code should implement any number of command classes and then add then to an FXUndoList instance. For an example of how this works, see the textedit example program from the FXRuby distribution.

Class Constants

[FXUndoList::ID_UNDO] Message identifier for the undo method. When a SEL_COMMAND message with this identifier is sent to an undo list, it undoes the last command. FXUndoList also provides a SEL_UPDATE handler for this identifier, that enables or disables the sender depending on whether it's possible to undo.

[FXUndoList::ID_UNDO_ALL] Message identifier for the “undo all” method. FXUndoList handles both the SEL_COMMAND and SEL_UPDATE messages for this message identifier.

[FXUndoList::ID_REDO] Message identifier for the redo method. When a SEL_COMMAND message with this identifier is sent to an undo list, it redoes the last command. FXUndoList also provides a SEL_UPDATE handler for this identifier, that enables or disables the sender depending on whether it's possible to redo.

[FXUndoList::ID_REDO_ALL] Message identifier for the “redo all” method. FXUndoList handles both the SEL_COMMAND and SEL_UPDATE messages for this message identifier.

[FXUndoList::ID_CLEAR] Message identifier for the “clear” method. FXUndoList handles both the SEL_COMMAND and SEL_UPDATE messages for this message identifier.

[FXUndoList::ID_REVERT] Message identifier for the “revert” method. FXUndoList handles both the SEL_COMMAND and SEL_UPDATE messages for this message identifier.

Instance Method Summary collapse

Methods included from Responder

#FXMAPFUNC, #FXMAPFUNCS, #FXMAPTYPE, #FXMAPTYPES, #addMapEntry, #assocIndex, #identifier, #messageMap

Methods inherited from FXObject

#bind, #handle, #load, #save, subclasses

Constructor Details

#initializeFXUndoList

Returns an initialized FXUndoList instance.


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/fox16/undolist.rb', line 94

def initialize
  # Be sure to call base class initialize
  super

  # Set up the message map for this instance
  FXMAPFUNC(SEL_COMMAND, ID_CLEAR,    "onCmdClear")
  FXMAPFUNC(SEL_UPDATE,  ID_CLEAR,    "onUpdClear")
  FXMAPFUNC(SEL_COMMAND, ID_REVERT,   "onCmdRevert")
  FXMAPFUNC(SEL_UPDATE,  ID_REVERT,   "onUpdRevert")
  FXMAPFUNC(SEL_COMMAND, ID_UNDO,     "onCmdUndo")
  FXMAPFUNC(SEL_UPDATE,  ID_UNDO,     "onUpdUndo")
  FXMAPFUNC(SEL_COMMAND, ID_REDO,     "onCmdRedo")
  FXMAPFUNC(SEL_UPDATE,  ID_REDO,     "onUpdRedo")
  FXMAPFUNC(SEL_COMMAND, ID_UNDO_ALL, "onCmdUndoAll")
  FXMAPFUNC(SEL_UPDATE,  ID_UNDO_ALL, "onUpdUndo")
  FXMAPFUNC(SEL_COMMAND, ID_REDO_ALL, "onCmdRedoAll")
  FXMAPFUNC(SEL_UPDATE,  ID_REDO_ALL, "onUpdRedo")

  # Instance variables
  @undolist = []
  @redolist = []
  @marker = nil
  @size = 0
end

Instance Method Details

#add(command, doit = false) ⇒ Object

Add new command (an FXCommand instance) to the list. If doit is true, the command is also executed.


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/fox16/undolist.rb', line 133

def add(command, doit=false)
  # Cut redo list
  cut

  # No command given?
  return true if command.nil?

  # Add it to the end of the undo list
  @undolist.push(command)

  # Execute it right now?
  command.redo if doit

  # Update size
  @size += command.size	# measured after redo

  # Update the mark distance
  @marker = @marker + 1 unless @marker.nil?

  # Done
  return true
end

#canRedo?Boolean

Return true if we can still redo some commands (i.e. the redo list is not empty).


224
225
226
# File 'lib/fox16/undolist.rb', line 224

def canRedo?
  (@redolist.empty? == false)
end

#canRevert?Boolean

Return true if there is a previously marked state that we can revert to.


232
233
234
# File 'lib/fox16/undolist.rb', line 232

def canRevert?
  (@marker != nil) && (@marker != 0)
end

#canUndo?Boolean

Return true if we can still undo some commands (i.e. the undo list is not empty).


216
217
218
# File 'lib/fox16/undolist.rb', line 216

def canUndo?
  (@undolist.empty? == false)
end

#clearObject

Clear the list


284
285
286
287
288
289
# File 'lib/fox16/undolist.rb', line 284

def clear
  @undolist.clear
  @redolist.clear
  @marker = nil
  @size = 0
end

#currentObject

Returns the current undo command.


239
240
241
# File 'lib/fox16/undolist.rb', line 239

def current
  @undolist.last
end

#cutObject

Cut the redo list


122
123
124
125
126
127
# File 'lib/fox16/undolist.rb', line 122

def cut
  @redolist.clear
  unless @marker.nil?
    @marker = nil if @marker < 0
  end
end

#markObject

Mark current state


322
323
324
# File 'lib/fox16/undolist.rb', line 322

def mark
  @marker = 0
end

#marked?Boolean

Return true if the undo list is marked.


336
337
338
# File 'lib/fox16/undolist.rb', line 336

def marked?
  @marker == 0
end

#onCmdClear(sender, sel, ptr) ⇒ Object

:nodoc:


368
369
370
371
# File 'lib/fox16/undolist.rb', line 368

def onCmdClear(sender, sel, ptr) # :nodoc:
  clear
  return 1
end

#onCmdRedo(sender, sel, ptr) ⇒ Object

:nodoc:


354
355
356
357
# File 'lib/fox16/undolist.rb', line 354

def onCmdRedo(sender, sel, ptr) # :nodoc:
  self.redo
  return 1
end

#onCmdRedoAll(sender, sel, ptr) ⇒ Object

:nodoc:


401
402
403
404
# File 'lib/fox16/undolist.rb', line 401

def onCmdRedoAll(sender, sel, ptr) # :nodoc:
  redoAll
  return 1
end

#onCmdRevert(sender, sel, ptr) ⇒ Object

:nodoc:


382
383
384
385
# File 'lib/fox16/undolist.rb', line 382

def onCmdRevert(sender, sel, ptr) # :nodoc:
  revert
  return 1
end

#onCmdUndo(sender, sel, ptr) ⇒ Object

:nodoc:


340
341
342
343
# File 'lib/fox16/undolist.rb', line 340

def onCmdUndo(sender, sel, ptr) # :nodoc:
  undo
  return 1
end

#onCmdUndoAll(sender, sel, ptr) ⇒ Object

:nodoc:


396
397
398
399
# File 'lib/fox16/undolist.rb', line 396

def onCmdUndoAll(sender, sel, ptr) # :nodoc:
  undoAll
  return 1
end

#onUpdClear(sender, sel, ptr) ⇒ Object

:nodoc:


373
374
375
376
377
378
379
380
# File 'lib/fox16/undolist.rb', line 373

def onUpdClear(sender, sel, ptr) # :nodoc:
  if canUndo? || canRedo?
	sender.handle(self, Fox.MKUINT(FXWindow::ID_ENABLE, SEL_COMMAND), nil)
  else
	sender.handle(self, Fox.MKUINT(FXWindow::ID_DISABLE, SEL_COMMAND), nil)
  end
  return 1
end

#onUpdRedo(sender, sel, ptr) ⇒ Object

:nodoc:


359
360
361
362
363
364
365
366
# File 'lib/fox16/undolist.rb', line 359

def onUpdRedo(sender, sel, ptr) # :nodoc:
  if canRedo?
	sender.handle(self, Fox.MKUINT(FXWindow::ID_ENABLE, SEL_COMMAND), nil)
  else
	sender.handle(self, Fox.MKUINT(FXWindow::ID_DISABLE, SEL_COMMAND), nil)
  end
  return 1
end

#onUpdRevert(sender, sel, ptr) ⇒ Object

:nodoc:


387
388
389
390
391
392
393
394
# File 'lib/fox16/undolist.rb', line 387

def onUpdRevert(sender, sel, ptr) # :nodoc:
  if canRevert?
	sender.handle(self, Fox.MKUINT(FXWindow::ID_ENABLE, SEL_COMMAND), nil)
  else
	sender.handle(self, Fox.MKUINT(FXWindow::ID_DISABLE, SEL_COMMAND), nil)
  end
  return 1
end

#onUpdUndo(sender, sel, ptr) ⇒ Object

:nodoc:


345
346
347
348
349
350
351
352
# File 'lib/fox16/undolist.rb', line 345

def onUpdUndo(sender, sel, ptr) # :nodoc:
  if canUndo?
	sender.handle(self, Fox.MKUINT(FXWindow::ID_ENABLE, SEL_COMMAND), nil)
  else
	sender.handle(self, Fox.MKUINT(FXWindow::ID_DISABLE, SEL_COMMAND), nil)
  end
  return 1
end

#redoObject

Redo next command


174
175
176
177
178
179
180
181
182
183
184
# File 'lib/fox16/undolist.rb', line 174

def redo
  unless @redolist.empty?
	command = @redolist.pop
	command.redo
	@undolist.push(command)
	@size += command.size
	@marker = @marker + 1 unless @marker.nil?
	return true
  end
  return false
end

#redoAllObject

Redo all commands


196
197
198
# File 'lib/fox16/undolist.rb', line 196

def redoAll
  redo while canRedo?
end

#redoNameObject

Return the name of the first available redo command. If no redo command is available, returns nil.


259
260
261
262
263
264
265
# File 'lib/fox16/undolist.rb', line 259

def redoName
  if canRedo?
    @redolist.last.redoName
  else
    nil
  end
end

#revertObject

Revert to marked


203
204
205
206
207
208
209
210
# File 'lib/fox16/undolist.rb', line 203

def revert
  unless @marker.nil?
	undo while (@marker > 0)
	redo while (@marker < 0)
	return true
  end
  return false
end

#trimCount(nc) ⇒ Object

Trim undo list down to at most nc commands.


294
295
296
297
298
299
300
301
# File 'lib/fox16/undolist.rb', line 294

def trimCount(nc)
  if @undolist.size > nc
	numRemoved = @undolist.size - nc
	@undolist[0, numRemoved].each { |command| @size -= command.size }
	@undolist[0, numRemoved] = nil
	@marker = nil if (@marker != nil && @marker > @undolist.size)
  end
end

#trimSize(sz) ⇒ Object

Trim undo list down to at most size.


306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/fox16/undolist.rb', line 306

def trimSize(sz)
  if @size > sz
	s = 0
	@undolist.reverse.each_index { |i|
      j = @undolist.size - (i + 1)
      s += @undolist[j].size
      @undolist[j] = nil if (s > sz)
	}
	@undolist.compact!
	@marker = nil if (@marker != nil && @marker > @undolist.size)
  end
end

#undoObject

Undo last command.


159
160
161
162
163
164
165
166
167
168
169
# File 'lib/fox16/undolist.rb', line 159

def undo
  unless @undolist.empty?
	command = @undolist.pop
	@size -= command.size
	command.undo
	@redolist.push(command)
	@marker = @marker - 1 unless @marker.nil?
	return true
  end
  return false
end

#undoAllObject

Undo all commands


189
190
191
# File 'lib/fox16/undolist.rb', line 189

def undoAll
  undo while canUndo?
end

#undoCountObject

Returns the number of undo records.


270
271
272
# File 'lib/fox16/undolist.rb', line 270

def undoCount
  @undolist.size
end

#undoNameObject

Return the name of the first available undo command. If no undo command is available, returns nil.


247
248
249
250
251
252
253
# File 'lib/fox16/undolist.rb', line 247

def undoName
  if canUndo?
    current.undoName
  else
    nil
  end
end

#undoSizeObject

Returns the total size of undo information.


277
278
279
# File 'lib/fox16/undolist.rb', line 277

def undoSize
  @size
end

#unmarkObject

Unmark undo list


329
330
331
# File 'lib/fox16/undolist.rb', line 329

def unmark
  @marker = nil
end