Wie soll sich "Undo Typing" verhalten?

12

Ich implementiere eine Java-App, die einen Undo / Redo-Stack enthält. Ich habe festgestellt, dass Sie in einigen Apps (z. B. TextEdit unter Mac OS X) nach dem Eingeben von Text im Menü Bearbeiten die Option "Eingabe rückgängig machen" auswählen können. Ich würde so etwas gerne auch in meine App implementieren, aber es fällt mir wirklich schwer, Richtlinien zu finden, wie es sich verhalten soll.

Nach einigem Hin und Her schätze ich, wie sich das Rückgängigmachen von TextEdit verhält:

  • Wenn der Benutzer ein neues Zeichen eingibt (oder den Löschschlüssel eingibt), fügen Sie es in das vorherige Undo Typing-Element ein, wenn sich eines oben im Undo-Stapel befindet, es sei denn, eine der folgenden Situationen tritt auf
  • Erstellen Sie immer ein neues Element zum Rückgängigmachen der Eingabe, nachdem der Benutzer nach mindestens 15 Sekunden Inaktivität die Eingabe fortgesetzt hat
  • Erstellen Sie immer ein neues Element zum Rückgängigmachen der Eingabe, nachdem der Benutzer über einen längeren Zeitraum hinweg eine Eingabe getätigt hat und eine bestimmte Bedingung erfüllt ist (es konnte nicht herausgefunden werden, ob dies zeitbasiert oder auf der Anzahl der Zeichen basiert).
  • Erstellen Sie immer ein neues Element zum Rückgängigmachen der Eingabe, wenn ein Text ausgewählt und dann gelöscht oder überschrieben wird (wenn Sie Text auswählen, keine Änderung vornehmen, dann zur ursprünglichen Einfügemarke zurückkehren und mit der Eingabe fortfahren, wird dies nicht ausgelöst).

In der Praxis scheint die Strategie von Apple zu funktionieren (zumindest funktioniert sie bei mir, wenn ich tippe), aber wie im letzten Punkt angemerkt, konnte ich die Regeln nicht wirklich herausfinden. Es scheint auch, dass andere Programme andere Regeln befolgen, wie z. B. Microsoft Word. Google hat keine definierte Liste von Regeln für die Implementierung von Undo Typing erstellt, und ich habe keine bewährten Methoden für das Verhalten gefunden. Wie soll es sich also verhalten? Oder liegt es nur an den Launen des Programmierers?

EDIT: Nur zur Verdeutlichung, ich bin im Moment nicht an Implementierungsdetails interessiert. Ich bin besonders neugierig, ob ein maßgeblicher Verweis (z. B. Best Practices oder Benutzeroberflächendokument) vorhanden ist, der dies beschreibt oder beschreibt, wie er in mehreren Produkten implementiert wird.

Donnerschmiede
quelle
Mein Vorschlag: Komprimieren Sie die Änderungen bis zu dem Punkt, an dem es immer noch möglich ist, die genaue Reihenfolge der gedrückten Tasten aus den Rückgängig-Informationen zu rekonstruieren. Dies bedeutet zum Beispiel, dass, wenn der Benutzer etwas eingibt und es sofort mit der Rücktaste löscht, ein Undo-Punkt dazwischen liegen sollte.
Ambroz Bizjak
Möglicherweise können Sie auch jedes Mal, wenn der Benutzer eine neue Zeile erstellt, und jedes Mal, wenn die Leertaste unmittelbar nach der Zeicheneingabe verwendet wird, ein neues Element "Eingabe rückgängig machen" hinzufügen. IMO 15 Sekunden Wartezeit, bevor ein neues "Undo Typing Item" etwas lang sein könnte, aber das bin nur ich. (Ich würde für etwa 5 Sekunden gehen)
user82529
Oder vielleicht sollte die "genaue Reihenfolge der gedrückten Tasten" auf "den Status des Textes nach jeder Änderung" gelockert werden. Damit soll verhindert werden, dass Text durch Komprimierung verloren geht.
Ambroz Bizjak
Für mich sieht es so aus, als würde TextEdit Leerzeichen zusammenführen und mit dem letzten Undo Typing-Element löschen, sofern die anderen Bedingungen nicht erfüllt sind. Das 124<delete>3Rückgängigmachen und Wiederherstellen führt zu 123. Ich vermute, der Vorteil davon ist, dass es den endgültigen Zustand des Textes des Benutzers ergibt, ähnlich wie der obige Vorschlag.
Thunderforge
Haben Sie schon versucht, Patente zu suchen? (Die Regeln werden normalerweise in der Bibliotheksschicht codiert und nicht dem Benutzercode ausgesetzt.)
Donal Fellows

Antworten:

5

Wenn Sie nach einer maßgeblichen Quelle suchen, finden Sie das beste Material zum Thema Mac im Undo Architecture- Dokument von Apple.

Ich glaube nicht, dass Sie eine Liste von Regeln finden werden, wann Sie undo-Ereignisse zusammenführen oder nicht. Was sich für eine Anwendung richtig anfühlt, ist für eine andere nicht unbedingt sinnvoll. Das Zusammenführen von Tastenanschlägen in einem Texteditor ist beispielsweise sinnvoll, da der Benutzer einen Absatz wahrscheinlich als eine einzelne Aktion und nicht als 539 separate Aktionen eingibt und der Benutzer nicht 539 Mal rückgängig machen muss, um sie abzurufen bis zu dem Punkt, an dem sie waren, bevor sie diesen Absatz tippten. Aber wie sieht es mit Verschiebevorgängen an einer Form in einem Zeichenprogramm aus? Oder sequentielle Anpassungen an einer Füllfarbe? Abhängig von der Art Ihres Programms können Sie ein gutes Argument dafür abgeben, dass diese zusammengeführt werden oder nicht.

Erstellen Sie immer ein neues Element zum Rückgängigmachen der Eingabe, nachdem der Benutzer über einen längeren Zeitraum hinweg eine Eingabe getätigt hat und eine bestimmte Bedingung erfüllt ist (es konnte nicht herausgefunden werden, ob dies zeitbasiert oder auf der Anzahl der Zeichen basiert).

Es basiert auf dem automatischen Speichern. Zum Glück ist der TextEdit-Quellcode verfügbar und gut kommentiert. Ich denke, wenn Sie es sich ansehen, werden Sie eine bessere Vorstellung davon bekommen, was los ist und warum. Beispielsweise:

- (void)saveToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation completionHandler:(void (^)(NSError *error))handler {
    // Note that we do the breakUndoCoalescing call even during autosave, which 
    // means the user's undo of long typing will take them back to the last spot an 
    // autosave occured. This might seem confusing, and a more elaborate solution may 
    // be possible (cause an autosave without having to breakUndoCoalescing), but since 
    // this change is coming late in Leopard, we decided to go with the lower risk fix.
    [[self windowControllers] makeObjectsPerformSelector:@selector(breakUndoCoalescing)];
 ...

Ich weiß, Sie sagten, dass Sie noch nicht an Implementierungsdetails interessiert sind, aber wenn Sie sich die Art und Weise ansehen, wie Apple TextEdit implementiert, können Sie über die Entscheidungen informieren, die Sie für Ihre eigene Anwendung treffen.

Caleb
quelle
1
Ich denke, ich erkläre das für die beste Antwort. Ich freue mich, dass Sie den Link zur Implementierung von Apple sowie einen Code für das von mir bereitgestellte Beispiel angeben. Ich denke, Sie haben jedoch Recht, es basiert im Allgemeinen auf den Anforderungen der Anwendung, und niemand hat sich wirklich bemüht, zu standardisieren, was diese Anforderungen sind und wie sie angegangen werden können.
Thunderforge
1

bei Tastendruck -> Timer, der Ihren Leerlauf anzeigt, startet

bei Tastendruck / Timer läuft -> Timer zurücksetzen

Bei gedrückter Taste / kein Timer läuft -> Passen Sie die Zellenblöcke neu an, um sich auf einen neuen Zustand vorzubereiten, wenn sich die Position ändert

Idle-Timer läuft ab -> Neuen Undo-Zustand herstellen

Ich würde Tastendruckidentitäten nicht verfolgen. Ich würde in zellulare Textblöcke (nach Anzahl der Zeichen) aufteilen, mit denen Sie die Position anhand von Offsets von den Anfangspositionen der nächsten Zelle verfolgen können, damit Sie nicht jedes Mal den gesamten Status eines Tolstoy-Romans speichern müssen, wenn ein Zeitgeber im Leerlauf abgelaufen ist . Das Nachjustieren dieser Offsets, wenn Zellen bearbeitet werden, bevor andere Zellen bearbeitet werden, ist der schwierige Teil.

Erik Reppen
quelle