Jak powinno się zachowywać „Cofanie pisania”?

12

Wdrażam aplikację Java, która zawiera stos Cofnij / Ponów. Zauważyłem, że niektóre aplikacje (takie jak TextEdit w systemie Mac OS X) pozwalają wybrać opcję „Cofnij wpisywanie” z menu Edycja po wpisaniu tekstu. Chciałbym również zaimplementować tego rodzaju rzeczy w mojej aplikacji, ale bardzo trudno mi znaleźć wytyczne dotyczące tego, jak powinno się to zachowywać.

Z pewnymi próbami i błędami, moje najlepsze przypuszczenie o tym, jak zachowuje się funkcja Cofnij, to:

  • Gdy użytkownik wpisze nowy znak (lub wpisze klawisz Delete), scal go z poprzednim elementem wpisywania Cofnij, jeśli znajduje się on na szczycie stosu Cofnij, chyba że wystąpi jedna z następujących sytuacji
  • Zawsze twórz nowy element Cofnij, gdy użytkownik kontynuuje pisanie po co najmniej 15 sekundach bezczynności
  • Zawsze twórz nowy element Cofnij wpisywanie po tym, jak użytkownik pisze przez dłuższy okres czasu i spełniony jest pewien warunek (nie mogę ustalić, czy był to czas, czy liczba znaków).
  • Zawsze twórz nowy element Cofnij wpisywanie, gdy dowolny tekst jest zaznaczony, a następnie usunięty lub nadpisany (zaznaczenie tekstu, nie wprowadzanie zmian, a następnie powrót do pierwotnego punktu wstawiania i kontynuowanie pisania nie powoduje tego)

W praktyce strategia Apple wydaje się działać (przynajmniej działa na mnie, gdy piszę), ale jak zauważyłem w ostatnim punkcie, tak naprawdę nie byłem w stanie zrozumieć zasad. Wygląda na to, że inne programy stosują inne reguły, takie jak Microsoft Word. Google nie odkrył zdefiniowanej listy reguł dla jakiejkolwiek implementacji Cofnij Pisanie i nie natknąłem się na żadne najlepsze praktyki dotyczące tego, jak powinna się zachowywać. Jak więc powinien się zachowywać? A może zależy to tylko od kaprysu programisty?

EDYCJA: Żeby wyjaśnić, nie jestem teraz zainteresowany szczegółami implementacji. Jestem szczególnie ciekawy, czy istnieje wiarygodne odniesienie (np. Najlepsze praktyki lub dokument interfejsu użytkownika) opisujące to lub opis sposobu, w jaki jest on wdrażany w wielu produktach.

Thunderforge
źródło
Moja sugestia: skompresuj modyfikacje do punktu, w którym nadal można zrekonstruować dokładną sekwencję naciśniętych klawiszy na podstawie informacji o cofnięciu i nie więcej. Na przykład oznacza to, że jeśli użytkownik wpisze coś i natychmiast użyje backspace, aby go usunąć, pomiędzy nimi powinien znajdować się punkt cofania.
Ambroz Bizjak
Być może możesz również dodać nowy element „Cofnij wpisywanie” za każdym razem, gdy użytkownik utworzy nowy wiersz, a może za każdym razem, gdy spacja zostanie użyta natychmiast po wprowadzeniu znaków. IMO 15 sekund czasu oczekiwania na nowy element „Cofnij wpisywanie” może być trochę długi, ale to tylko ja. (
Chodziłbym
A może „dokładna sekwencja naciśniętych klawiszy” powinna być rozluźniona do „stanu tekstu po każdej modyfikacji”. Chodzi o to, aby zapobiec zgubieniu tekstu z powodu kompresji.
Ambroz Bizjak
Wydaje mi się, że TextEdit łączy spacje i usuwa ostatni element wpisywania Cofnij, pod warunkiem, że pozostałe warunki nie są spełnione. Tak więc 124<delete>3cofnięcie i ponowienie powoduje 123. Myślę, że zaletą tego jest to, że skutkuje to końcowym stanem tekstu użytkownika, podobnie jak powyższa sugestia.
Thunderforge
Czy próbowałeś już szukać patentów? (Reguły są zwykle kodowane w warstwie biblioteki, nie są narażone na kod użytkownika.)
Donal Fellows

Odpowiedzi:

5

Jeśli szukasz wiarygodnego źródła, myślę, że najlepszy materiał na Maca znajdziesz w dokumencie Undo Architecture od Apple.

Nie sądzę jednak, abyś znalazł listę reguł określających, kiedy powinieneś lub nie powinieneś łączyć cofania wydarzeń. To, co wydaje się odpowiednie dla jednej aplikacji, niekoniecznie ma sens dla innej. Na przykład koalescencja klawiszy ma sens w edytorze tekstu, ponieważ użytkownik prawdopodobnie zobaczy, że wpisanie akapitu jest pojedynczą akcją, a nie 539 oddzielnymi akcjami, a także dlatego, że nie chcesz, aby użytkownik musiał cofać 539 razy, aby uzyskać do tego stopnia, w jakim byli, zanim napisali ten akapit. Ale co z operacjami przenoszenia kształtu na programie do rysowania? A może sekwencyjne korekty koloru wypełnienia? Możesz uzasadnić ich połączenie lub nie, w zależności od charakteru twojego programu.

Zawsze twórz nowy element Cofnij wpisywanie po tym, jak użytkownik pisze przez dłuższy okres czasu i spełniony jest pewien warunek (nie mogę ustalić, czy był to czas, czy liczba znaków).

Opiera się na autozapisie. Na szczęście dla Ciebie kod źródłowy TextEdit jest dostępny i dobrze skomentowany. Myślę, że jeśli na to spojrzysz, zrozumiesz, co się dzieje i dlaczego. Na przykład:

- (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)];
 ...

Wiem, że powiedziałeś, że nie jesteś jeszcze zainteresowany szczegółami implementacji, ale patrząc na sposób, w jaki Apple wdrożył TextEdit, może wpływać na decyzje podejmowane w związku z własną aplikacją.

Caleb
źródło
1
Myślę, że zadeklaruję tę najlepszą odpowiedź. Dziękujemy za podanie linku do implementacji Apple, a także kodu do konkretnego przykładu, który podałem. Myślę, że masz rację, ogólnie rzecz biorąc, jest on oparty na potrzebach aplikacji i nikt tak naprawdę nie starał się ujednolicić tych potrzeb i sposobu ich zaspokojenia.
Thunderforge
1

po keydown -> licznik czasu reprezentujący czas bezczynności

po keydown / timer-running -> reset timer

po keydown / no timer-running -> dostosuj bloki komórek, aby przygotować się do nowego zachowanego stanu wraz ze zmianą pozycji

Czas bezczynności wyczerpuje się -> Ustal nowy stan cofania

Nie śledziłbym tożsamości naciśnięć klawiszy. Podzielę się na komórkowe bloki tekstu (według liczby znaków), które pozwalają śledzić pozycję za pomocą przesunięć względem początkowych pozycji najbliższej komórki, abyś nie musiał zapisywać całego stanu powieści tolstoy za każdym razem, gdy upłynie czas bezczynności . Ponowne dostosowanie tych przesunięć, gdy komórki przed edycją innych komórek jest trudną częścią.

Erik Reppen
źródło