[JAVA] Erstellen Sie einen wöchentlichen Git-GUI-Client. [5] Erste Desktop-App

Es ist nicht monatlich, also ist es sicher. Grundsätzlich die Geschichte von Swing.

Zusammenfassung bis zur vorherigen Ausgabe

[\ 1 ] Stage / Unstage-Grundkenntnisse

5 Dinge, die man für Line-by-Line Stage / Unstage tun kann

1. Ausgangsdifferenz als Original-Patch 2. Wählen Sie die Linie aus, die Sie inszenieren / aufheben möchten 3. Bearbeiten Sie den Körper von Hunk`` 4. Berechnen Sie den Hunk-Header neu`` 5. Wenden Sie den letzten Patch an

[\ 2 ] Stage / Unstage unvollständige Erfassung

Ich konnte JGit nicht verwenden, also habe ich über die Verwendung von git.exe gesprochen.

[\ 3 ] Bearbeitung von Stage- / Unstage-Patches

3. Bearbeiten Sie den Körper von Hunk`` 4. Berechnen Sie den Hunk-Header neu``

[4] diff et al.

1. Ausgangsdifferenz als Original-Patch

Dieses Problem

2. Wählen Sie die Linie aus, die Sie inszenieren / aufheben möchten

進捗.gif

Es muss jedoch angezeigt werden, um ausgewählt zu werden. Diesmal geht es um die Anzeige.

Es ist schwierig, über die Benutzeroberfläche nachzudenken

Als GUI-Anwendung

Es scheint notwendig zu sein, solche Dinge im Design zu reflektieren, Ich denke hier nicht grundsätzlich darüber nach. Ich möchte "Mein Idiot, der sich mit meinen Gedanken befasst" machen.

Denk einfach darüber nach und sei glücklich.

Zum Beispiel UITableView

Das erste, was ich mir vorgestellt habe, war Es handelt sich um eine Sammlungsansicht mit einem Abschnitt wie UITableView von iOS. Aber Sie und Java, das ist JVM.

Als UI zur teilweisen Auswahl von Diff mit Swing schnell Ich habe mich für JList entschieden, weil es am einfachsten zu sein scheint. Der Diff, der die Quelle des Patches ist, wird zeilenweise in der Liste angezeigt und ausgewählt.

Ich wollte Zeile für Zeile aktualisieren, also habe ich es JTable gemacht (später beschrieben), Da es sich um eine JTable mit nur einer Spalte handelt, ist die Grundverwendung dieselbe.

Mo-ähnliches Gefühl

Übrigens, selbst wenn Sie es in einer Liste anzeigen, müssen Sie das Diff nicht zeilenweise anzeigen. Sie können den Text in jeder Zeile der Liste anzeigen und dort auswählen lassen. Ich dachte natürlich, dass die Auswahleinheit eine Zeile in der Liste ist.

Ungefähr zu dieser Zeit habe ich das Gefühl, in der Entwicklung mobiler Anwendungen zu stecken. (Ich arbeite hauptsächlich an der Entwicklung nativer Apps für iOS und Android)

Stage / Unstage-Trigger nach Auswahl

Nach der Auswahl benötigen Sie eine Aktion, die Stage / Unstage auslöst. Wenn Sie sich SourceTree ansehen, sehen Sie eine Schaltfläche und ein Kontextmenü. Rechtsklick ist ein Aufwand, den Sie regelmäßig verwenden müssen. Es ist auch schwierig, über die Position und Form des Knopfes nachzudenken.

Deshalb habe ich beschlossen, auf den Header-Teil des Diff zu klicken.

Anzeige von Diff

hunk

Es ist einfacher, die von "git diff" erhaltenen Daten so anzuzeigen, wie sie sind. Lassen Sie uns sie also in Stückeinheiten anzeigen.

Der hier erwähnte Diff-Header enthält mehrere Zeilen für jede Datei. Von der Zeile, die mit diff --git beginnt, bis kurz vor der Hunk-Header-Zeile. Der Hunk-Header hier ist eine Zeile, die mit "@@" beginnt.

<diff-per-file>
	<diff-header />
	<hunk>
		<hunk-header />
		<hunk-body />
	</hunk>
	<hunk>
		<hunk-header />
		<hunk-body />
	</hunk>
</diff-per-file>

<!--Möglicherweise gibt es kein Stück wie Bilder-->
<diff-per-file>
	<diff-header />
</diff-per-file>

Das Git Diff hat die obige Struktur,

  1. Es wäre schön zu wissen, welche Datei in Hunk-Einheiten unterschiedlich ist
  2. Ich versuche, durch Klicken auf den Header-Teil zu inszenieren / zu entfernen. Ich bin also froh, wenn er breiter ist

Zeigen Sie aus diesem Grund den Diff-Header mit jedem Hunk an.

<diff-per-file>
	<diff-header />
	<hunk>
		<hunk-header />
		<hunk-body />
	</hunk>
	<diff-header />
	<hunk>
		<hunk-header />
	    <hunk-body />
	</hunk>
</diff-per-file>

<diff-per-file>
	<diff-header />
	<hunk>
		<hunk-header dummy="new file" />
		<hunk-body img="icon.png " />
	</hunk>
</diff-per-file>

Wenn Sie mehrere Hunks desselben Diff kombinieren, wird der Diff-Header dupliziert. Es scheint kein Problem zu geben, selbst wenn sie auf einmal auf dem Patch ausgegeben werden. (Grundsätzlich bewerbe ich mich jedoch nur auf Hunk-Basis, sodass möglicherweise ein verstecktes Problem vorliegt.)

Hunk-Header

Daher werden mehrere Textzeilen in einer Zeile der Liste angezeigt. JLabel usw. kann HTML (wie?) Zusammen mit <html> </ html> setzen.

Collector<CharSequence, ?, String> toHtml = Collectors.joining(
            "</nobr><br><nobr>",
            "<html><nobr>",
            "</nobr></html>");
Arrays.stream(Zeichenfolge im Header-Teil.split("\n")).collect(toHtml)

Ich frage mich, ob " </ nobr>" jetzt oder in Zukunft in jeder Umgebung verwendet werden kann, aber es ist nützlich.

Stück Körper

Die Ausgabe von "git diff" ist so wie sie ist. Es ist leicht zu verstehen, ob die Farben für die Zeile Hinzufügen, Löschen und Kontext unterschiedlich sind.

Asynchrone Bilderfassung

Beim Hinzufügen oder Löschen von Bildern (z. B. Binärdateien) wird dies in Dateieinheiten behandelt Das Unit Hunk existiert nicht und erscheint nicht in der Ausgabe von git diff.

Ich möchte das Bild jedoch anzeigen, da es eine große Sache ist. In der vorherigen Ausgabe haben wir die Methode und die Vorsichtsmaßnahmen erwähnt.

Bei der Anzeige in einer Liste

  • Im Gegensatz zu anderen Hunks habe ich zum Zeitpunkt von "git diff" keine Bilddatei
  • Das Erstellen eines Bildobjekts dauert einige Zeit

In diesem Sinne gibt es zwei Anzeigemethoden.

  • Warten Sie, bis das Bild fertig ist, bevor Sie die Liste anzeigen
  • Zeigen Sie den Text jedes Hunks in der Liste an und aktualisieren Sie später nur das Bild

Ich bin nicht glücklich zu warten, also lassen Sie uns anzeigen, was zuerst angezeigt werden kann.

(Ich dachte nicht, dass die Implementierung mühsam wäre, deshalb habe ich mich natürlich für Letzteres entschieden, aber ich denke, es ist absolut schwierig zu warten, da dies von der Leistung des lokalen Computers abhängt und nicht über das Netzwerk.)

Aktualisieren Sie die Listenanzeige zeilenweise

JList scheint jedoch nicht in der Lage zu sein, zeilenweise zu aktualisieren. Wir verwenden JTable also mit nur einer Spalte.

Als Ergebnis verschiedener Versuche habe ich es in eine Zeile mit nur Text und eine Zeile mit nur Bildern unterteilt. Das Aktualisieren in der folgenden Reihenfolge ergab die gewünschte Leistung.

  1. Bestimmen Sie zuerst die Höhe der Textzeile
  2. Starten Sie die asynchrone Erfassung von Bildern in Bildzeilen
  3. Wenn Sie das Bild haben, bestimmen Sie die Höhe der Linie aus dem Bild

Das Folgende beinhaltet Hacks, die von der internen Implementierung von Swing abhängen Abhängig von der Version funktionieren möglicherweise nicht die gleiche Idee und derselbe Code. Ich überprüfe javac 1.8.0_144. (Verstehst du, dass es das gleiche ist wie die Javac-Version?) (Gibt es übrigens Pläne, die bestehenden Komponenten von Swing in Zukunft dramatisch zu verbessern?)

Bestimmen Sie zuerst die Höhe der Textzeile

Wenn jede Zeile in JTable angezeigt / aktualisiert werden muss, wird der für jede Spalte festgelegte TableCellRenderer aufgerufen. TableCellRenderer ist eine Schnittstelle.

public interface TableCellRenderer {

	Component getTableCellRendererComponent(JTable table, 
	                                        Object value,
	                                        boolean isSelected, 
	                                        boolean hasFocus,
	                                        int row, 
	                                        int column);
}

Es sollte verschiedene Möglichkeiten geben, jede Zeile zu aktualisieren. Hier verwenden wir "JTable # setRowHeight (int row, int rowHeight)". Es ist wichtig, die Höhe von Linie zu Linie zu ändern.

Sie können die Höhe des Textes ermitteln, indem Sie den Text in JLabel einfügen. Erstellen Sie ein JLabel und legen Sie die Höhe fest, bevor der TableCellRenderer aufgerufen wird.

Die Höhe jeder Zeile wird aktualisiert, wenn sich die der Tabelle zugeordneten Daten ändern. Dies ist ein Beispielcode.

//Ich werde zuerst die setRowHeight der Textzeile zusammenstellen
preRender = () -> {
    //Wenn Sie eine der folgenden Aktionen nicht ausführen, hängt die maximale Anzahl der Zeilen in der Tabelle von der Anzahl der ursprünglich angezeigten Zeilen ab.
    //Wahrscheinlich rowModel in JTable= null;Ich denke du brauchst
    this.table.setRowHeight(1);
//    setRowSorter(null);
//    tableChanged(new TableModelEvent(getModel()));
    final int size = dataModel.getSize();
    for (int i = 0; i < size; i++) {
        final ListItem item = dataModel.getElementAt(i);
        final ImageHolder imageHolder = item.imageHolder();
        //Wenn nicht eine Bildzeile
        if (imageHolder == null || !imageHolder.hasLoader()) {
            //Bargeld nicht, weil es keine großen Kosten sein sollte
            final JLabel label = new JLabel();
            this.renderer.render(label, item, false, null);
            final int height = label.getPreferredSize().height;
            table.setRowHeight(i, height);
        }
    }
};

Ich habe es im Beispielcode geschrieben, aber als Einschränkung,

  • this.table.setRowHeight(1);
  • setRowSorter(null);
  • tableChanged(new TableModelEvent(getModel()));

Wenn Sie nicht anrufen usw., hängt die maximale Anzahl von Zeilen in der Tabelle von der Anzahl der ursprünglich angezeigten Zeilen ab. Wenn Sie zuerst 3 Zeilen anzeigen, kann die Tabelle nur 3 Zeilen anzeigen. Ich bin mir nicht sicher, warum das passiert, aber Das Initialisieren des "Private SizeSequence rowModel" der JTable scheint sich wie erwartet zu verhalten.

Rufen Sie "JTable # setRowHeight (int row, int rowHeight)" nicht mehr als einmal für dieselbe Zeile auf. Es kann sein, dass.

Starten Sie die asynchrone Erfassung von Bildern in Bildzeilen

Wie beim Text können Sie im Voraus beginnen, Ich hatte also keine Leistungsprobleme Verwenden Sie TableCellRenderer # getTableCellRendererComponent.

Auf jeden Fall, Zumindest beim Aktualisieren der umgebenden Zeilen wird TableCellRenderer # getTableCellRendererComponent aufgerufen Es muss so implementiert werden, dass die Bildaufnahme und der Rückruf nach der Aufnahme nur einmal erfolgen.

Sobald Sie das Bild erhalten haben, bestimmen Sie die Höhe der Linie aus dem Bild

Da die Anzeige außerhalb von TableCellRenderer # getTableCellRendererComponent nicht geändert werden kann, Geben Sie dem zugehörigen Element nach dem Abrufen des Bildes das Bild Rufen Sie JTable # setRowHeight (int row, int rowHeight) auf. Dann wird TableCellRenderer # getTableCellRendererComponent erneut aufgerufen.

final TableColumn tableColumn = this.table.getColumnModel().getColumn(0);
tableColumn.setCellRenderer((table, value, isSelected, hasFocus, row, column) -> {
        final ListItem item = (ListItem) value;
        final JLabel label = new JLabel();
        //Starten Sie hier die Bildaufnahme oder legen Sie ein Bild fest
        this.renderer.render(label, item, isSelected, imageIcon -> {
                //Nach der Bildaufnahme
                final int iconHeight = imageIcon.getIconHeight();
                table.setRowHeight(row, iconHeight);
        });
        return label;
});

Fortschritt

Es ist ein Fortschritts-GIF, das jedes Mal bekannt ist und nichts mit dem Posten zu tun hat.

進捗_3.gif

Es gibt immer noch Fehler und Probleme, aber Sie können sich verpflichten. Ich möchte in der Lage sein, den Verlauf bald anzuzeigen.

Nachwort

Vorschau beim nächsten Mal

Sobald Sie anfangen zu schreiben

  • Sie können sehen, dass es funktioniert, auch wenn Sie nicht Ihr Bestes geben
  • Ich habe festgestellt, dass ich mit japanischen Dateinamen nicht umgehen kann

Ich wurde aus irgendeinem Grund müde und beschloss, mit der nächsten Ausgabe fortzufahren.

Aktuelle Situation

Ich habe angefangen, diese Serie und Apps zu schreiben Es war, weil ich in Rente ging und es genoss, arbeitslos zu sein.

Ich hatte noch eine Weile nicht vor zu arbeiten, Die Arbeit kam vom Himmel, also wurde ich freiberuflich tätig. Es war ein Fluss, in dem ich Programmierer wurde, also denke ich, dass es so weitergehen wird, wie es ist.

Das Neueste ist die Überarbeitung der iOS-App. Ich habe noch keinen Code geschrieben, aber Sie sollten "git commit" in Ihrer eigenen Anwendung verwenden. (Ich habe es noch nicht auf einem Mac ausgeführt, aber ich glaube an JVM)

Wenn Sie Arbeit zur Hand haben, sind Sie motivierter, Werkzeuge außerhalb der Arbeit herzustellen.

Swing

Es gibt keinen besonderen Grund, in Swing zu schreiben. Es gab nur "Ich möchte kein CSS schreiben" Ich wollte es als temporäre Implementierung für das Design tun, Es gibt kein besonderes Problem, daher plane ich, so fortzufahren, wie es ist.

Ich frage mich, welche Form für die Verteilung verwendet werden sollte.

Recommended Posts

Erstellen Sie einen wöchentlichen Git-GUI-Client. [5] Erste Desktop-App
Erstellen Sie einen wöchentlichen Git-GUI-Client [4] diff et al.
Erstellen Sie einen wöchentlichen Git-GUI-Client [2] für eine unvollständige Erfassung
Erstellen Sie eine neue App mit Rails
Versuchen Sie, eine Server-Client-App zu erstellen
[Rails6] Erstelle eine neue App mit Rails [Anfänger]
Erstellen Sie eine TODO-App in Java 7 Create Header
[Rails 5] Erstelle eine neue App mit Rails [Anfänger]
Erstellen Sie mit Spring Boot eine einfache Such-App
Ich habe versucht, eine LINE-Klon-App zu erstellen
Jetzt ist Git GUI Client selbst gemacht ist sehr beliebt!