refactor<Launcher>: rewrite title bar of Launcher

This commit is contained in:
leo 2020-12-31 11:26:33 +08:00
parent 567fad495b
commit 72f09e96af
3 changed files with 132 additions and 80 deletions

View file

@ -8,6 +8,7 @@
<Geometry x:Key="Icon.Bookmark">M192 0l0 1024 320-320 320 320 0-1024z</Geometry> <Geometry x:Key="Icon.Bookmark">M192 0l0 1024 320-320 320 320 0-1024z</Geometry>
<Geometry x:Key="Icon.Help">M512 96C282.2 96 96 282.2 96 512s186.2 416 416 416 416-186.2 416-416S741.8 96 512 96z m-8.6 608c-23.6 0-42.8-18-42.8-41.2 0-23 19.2-41.2 42.8-41.2 23.8 0 43 18 43 41.2 0 23.2-19 41.2-43 41.2z m80.4-193.8c-34.8 20.2-46.6 35-46.6 60.6v15.8h-69.4l-0.6-17.2c-3.4-41.2 11-66.8 47.2-88 33.8-20.2 48-33 48-57.8s-24-43-53.8-43c-30.2 0-52 19.6-53.6 49.2H384c1.4-64.4 49-110 129.4-110 75 0 126.6 41.6 126.6 101.4 0 39.8-19.2 67.2-56.2 89z</Geometry> <Geometry x:Key="Icon.Help">M512 96C282.2 96 96 282.2 96 512s186.2 416 416 416 416-186.2 416-416S741.8 96 512 96z m-8.6 608c-23.6 0-42.8-18-42.8-41.2 0-23 19.2-41.2 42.8-41.2 23.8 0 43 18 43 41.2 0 23.2-19 41.2-43 41.2z m80.4-193.8c-34.8 20.2-46.6 35-46.6 60.6v15.8h-69.4l-0.6-17.2c-3.4-41.2 11-66.8 47.2-88 33.8-20.2 48-33 48-57.8s-24-43-53.8-43c-30.2 0-52 19.6-53.6 49.2H384c1.4-64.4 49-110 129.4-110 75 0 126.6 41.6 126.6 101.4 0 39.8-19.2 67.2-56.2 89z</Geometry>
<Geometry x:Key="Icon.Detail">M888.832 0H135.168c-32.256 0-58.88 26.112-58.88 58.88v906.24c0 32.256 26.112 58.88 58.88 58.88h753.152c32.256 0 58.88-26.112 58.88-58.88v-906.24c0.512-32.768-26.112-58.88-58.368-58.88z m-164.864 176.64c30.72 0 55.808 25.088 55.808 55.808s-25.088 55.808-55.808 55.808-55.808-25.088-55.808-55.808 24.576-55.808 55.808-55.808z m-211.968 0c30.72 0 55.808 25.088 55.808 55.808S542.72 288.256 512 288.256s-55.808-25.088-55.808-55.808S481.28 176.64 512 176.64z m-211.968 0c30.72 0 55.808 25.088 55.808 55.808s-25.088 55.808-55.808 55.808-55.808-25.088-55.808-55.808 25.088-55.808 55.808-55.808z m208.896 606.208H285.184c-24.576 0-44.032-19.968-44.032-44.032 0-24.576 19.968-44.032 44.032-44.032h223.744c24.576 0 44.032 19.968 44.032 44.032 0 24.064-19.456 44.032-44.032 44.032z m229.888-211.968H285.184c-24.576 0-44.032-19.968-44.032-44.032 0-24.576 19.968-44.032 44.032-44.032h453.12c24.576 0 44.032 19.968 44.032 44.032 0.512 24.064-19.456 44.032-43.52 44.032z</Geometry> <Geometry x:Key="Icon.Detail">M888.832 0H135.168c-32.256 0-58.88 26.112-58.88 58.88v906.24c0 32.256 26.112 58.88 58.88 58.88h753.152c32.256 0 58.88-26.112 58.88-58.88v-906.24c0.512-32.768-26.112-58.88-58.368-58.88z m-164.864 176.64c30.72 0 55.808 25.088 55.808 55.808s-25.088 55.808-55.808 55.808-55.808-25.088-55.808-55.808 24.576-55.808 55.808-55.808z m-211.968 0c30.72 0 55.808 25.088 55.808 55.808S542.72 288.256 512 288.256s-55.808-25.088-55.808-55.808S481.28 176.64 512 176.64z m-211.968 0c30.72 0 55.808 25.088 55.808 55.808s-25.088 55.808-55.808 55.808-55.808-25.088-55.808-55.808 25.088-55.808 55.808-55.808z m208.896 606.208H285.184c-24.576 0-44.032-19.968-44.032-44.032 0-24.576 19.968-44.032 44.032-44.032h223.744c24.576 0 44.032 19.968 44.032 44.032 0 24.064-19.456 44.032-44.032 44.032z m229.888-211.968H285.184c-24.576 0-44.032-19.968-44.032-44.032 0-24.576 19.968-44.032 44.032-44.032h453.12c24.576 0 44.032 19.968 44.032 44.032 0.512 24.064-19.456 44.032-43.52 44.032z</Geometry>
<Geometry x:Key="Icon.NewTab">M490.667 85.333l42.667 0 0 853.333-42.667 0 0-853.333zM85.333 490.667l853.333 0 0 42.667-853.333 0 0-42.667z</Geometry>
<Geometry x:Key="Icon.ScrollLeft">M753.613 996.727L269.38 511.505 754.602 27.272z</Geometry> <Geometry x:Key="Icon.ScrollLeft">M753.613 996.727L269.38 511.505 754.602 27.272z</Geometry>
<Geometry x:Key="Icon.ScrollRight">M270.387 27.273L754.62 512.495 269.398 996.728z</Geometry> <Geometry x:Key="Icon.ScrollRight">M270.387 27.273L754.62 512.495 269.398 996.728z</Geometry>

View file

@ -47,18 +47,42 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition x:Name="openedTabsColumn" Width="*"/> <ColumnDefinition x:Name="openedTabsColumn" Width="*"/>
<ColumnDefinition Width="32"/> <ColumnDefinition Width="32"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Tabs --> <!-- Tabs -->
<ScrollViewer x:Name="openedTabsScroller" Grid.Column="0" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled"> <ScrollViewer x:Name="openedTabsScroller" Grid.Column="0" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled" CanContentScroll="True">
<TabControl x:Name="openedTabs" Padding="0" SnapsToDevicePixels="True" ItemsSource="{Binding ElementName=me, Path=Tabs}" SizeChanged="OpenedTabsSizeChanged"> <TabControl x:Name="openedTabs" Padding="0" SnapsToDevicePixels="True" ItemsSource="{Binding ElementName=me, Path=Tabs}" SizeChanged="OpenedTabsSizeChanged">
<TabControl.Style> <TabControl.Style>
<Style TargetType="{x:Type TabControl}"> <Style TargetType="{x:Type TabControl}">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}"> <ControlTemplate TargetType="{x:Type TabControl}">
<StackPanel Orientation="Horizontal" x:Name="HeaderPanel" Margin="6,4,0,0" IsItemsHost="True" SnapsToDevicePixels="True" KeyboardNavigation.TabIndex="1"/> <StackPanel Orientation="Horizontal" Margin="6,4,4,0">
<StackPanel Orientation="Horizontal" IsItemsHost="True" SnapsToDevicePixels="True" KeyboardNavigation.TabIndex="1"/>
<Button Margin="4,0,0,0" Click="NewTab" ToolTip="NEW PAGE" Width="24" Height="24" WindowChrome.IsHitTestVisibleInChrome="True">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="Opacity" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="newTabBG" BorderThickness="0" Background="Transparent" CornerRadius="2">
<Path Width="14" Height="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.NewTab}" Fill="{StaticResource Brush.FG}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="newTabBG" Property="Background" Value="{StaticResource Brush.BG4}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</StackPanel>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -67,12 +91,10 @@
<TabControl.Resources> <TabControl.Resources>
<converters:IntToRepoColor x:Key="IntToRepoColor"/> <converters:IntToRepoColor x:Key="IntToRepoColor"/>
</TabControl.Resources>
<DataTemplate DataType="{x:Type local:Launcher+ManagerTab}"> <TabControl.ItemTemplate>
<Path Width="14" Height="14" Margin="12,0" Fill="#FFF05133" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Home}"/> <DataTemplate>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Launcher+RepoTab}">
<Grid x:Name="BG" MinWidth="80" Margin="8,0" Background="Transparent"> <Grid x:Name="BG" MinWidth="80" Margin="8,0" Background="Transparent">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
@ -96,7 +118,7 @@
Content="{Binding Title}" Content="{Binding Title}"
Foreground="{StaticResource Brush.FG2}" FontFamily="Consolas" FontWeight="Bold"/> Foreground="{StaticResource Brush.FG2}" FontFamily="Consolas" FontWeight="Bold"/>
<Button Grid.Column="3" Click="CloseRepo" ToolTip="CLOSE"> <Button Grid.Column="3" Click="CloseTab" ToolTip="CLOSE">
<Path <Path
Width="8" Height="8" Width="8" Height="8"
Fill="{StaticResource Brush.FG}" Fill="{StaticResource Brush.FG}"
@ -109,10 +131,18 @@
<DataTrigger Binding="{Binding IsActive}" Value="True"> <DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter TargetName="Title" Property="Foreground" Value="{StaticResource Brush.FG}"/> <Setter TargetName="Title" Property="Foreground" Value="{StaticResource Brush.FG}"/>
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding Color}" Value="0"> <DataTrigger Binding="{Binding IsRepo}" Value="False">
<Setter TargetName="Icon" Property="Data" Value="{StaticResource Icon.Git}"/> <Setter TargetName="Icon" Property="Data" Value="{StaticResource Icon.Home}"/>
<Setter TargetName="Icon" Property="Fill" Value="{StaticResource Brush.FG}"/> <Setter TargetName="Icon" Property="Fill" Value="{StaticResource Brush.FG}"/>
</DataTrigger> </DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsRepo}" Value="True"/>
<Condition Binding="{Binding Color}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Icon" Property="Data" Value="{StaticResource Icon.Git}"/>
<Setter TargetName="Icon" Property="Fill" Value="{StaticResource Brush.FG}"/>
</MultiDataTrigger>
<MultiDataTrigger> <MultiDataTrigger>
<MultiDataTrigger.Conditions> <MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsActive}" Value="False"/> <Condition Binding="{Binding IsActive}" Value="False"/>
@ -122,11 +152,11 @@
</MultiDataTrigger> </MultiDataTrigger>
</DataTemplate.Triggers> </DataTemplate.Triggers>
</DataTemplate> </DataTemplate>
</TabControl.Resources> </TabControl.ItemTemplate>
<TabControl.ItemContainerStyle> <TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}"> <Style TargetType="{x:Type TabItem}">
<Setter Property="AllowDrop" Value="{Binding IsRepo}"/> <Setter Property="AllowDrop" Value="True"/>
<Setter Property="IsSelected" Value="{Binding IsActive, Mode=TwoWay}"/> <Setter Property="IsSelected" Value="{Binding IsActive, Mode=TwoWay}"/>
<Setter Property="Margin" Value="0"/> <Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/> <Setter Property="Padding" Value="0"/>
@ -136,13 +166,6 @@
<Grid SnapsToDevicePixels="True" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="{Binding Tooltip}"> <Grid SnapsToDevicePixels="True" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="{Binding Tooltip}">
<Border x:Name="BG" Margin="-1,0" SnapsToDevicePixels="True" Background="Transparent" CornerRadius="4,4,0,0"/> <Border x:Name="BG" Margin="-1,0" SnapsToDevicePixels="True" Background="Transparent" CornerRadius="4,4,0,0"/>
<Rectangle
x:Name="Splitter"
HorizontalAlignment="Left"
Width="1" Height="16"
Fill="{StaticResource Brush.FG2}"
Visibility="Hidden"/>
<Path <Path
x:Name="CornerLeft" x:Name="CornerLeft"
Width="6" Width="6"
@ -168,6 +191,13 @@
VerticalAlignment="Center" VerticalAlignment="Center"
ContentSource="Header" ContentSource="Header"
RecognizesAccessKey="True"/> RecognizesAccessKey="True"/>
<Rectangle
x:Name="Splitter"
HorizontalAlignment="Right"
Width="1" Height="16"
Fill="{StaticResource Brush.FG2}"
Visibility="Hidden"/>
</Grid> </Grid>
<ControlTemplate.Triggers> <ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True"> <Trigger Property="IsSelected" Value="True">
@ -196,7 +226,6 @@
<MultiTrigger.Conditions> <MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="False"/> <Condition Property="IsSelected" Value="False"/>
<Condition Property="IsMouseOver" Value="False"/> <Condition Property="IsMouseOver" Value="False"/>
<Condition Property="AllowDrop" Value="True"/>
</MultiTrigger.Conditions> </MultiTrigger.Conditions>
<Setter TargetName="Splitter" Property="Visibility" Value="Visible"/> <Setter TargetName="Splitter" Property="Visibility" Value="Visible"/>
</MultiTrigger> </MultiTrigger>

View file

@ -22,14 +22,31 @@ namespace SourceGit.UI {
/// </summary> /// </summary>
public class Tab : INotifyPropertyChanged { public class Tab : INotifyPropertyChanged {
private bool isActive = false; private bool isActive = false;
private Git.Repository repo = null;
private object page = null;
public string Title { get; set; } public Git.Repository Repo {
public string Tooltip { get; set; } get { return repo; }
public Git.Repository Repo { get; set; } set {
public object Page { get; set; } if (repo != value) {
repo = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Repo"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Title"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Tooltip"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsRepo"));
}
}
}
public bool IsRepo { public object Page {
get { return Repo != null; } get { return page; }
set {
if (page != value) {
page = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Page"));
}
}
} }
public int Color { public int Color {
@ -50,34 +67,24 @@ namespace SourceGit.UI {
} }
} }
public string Title {
get {
if (Repo == null) return "Repositories";
return Repo.Parent == null ? Repo.Name : $"{Repo.Parent.Name} : {Repo.Name}";
}
}
public string Tooltip {
get { return Repo == null ? "Repository Manager" : Repo.Path; }
}
public bool IsRepo {
get { return Repo != null; }
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
} }
/// <summary>
/// Manager tab
/// </summary>
public class ManagerTab : Tab {
public ManagerTab() {
Title = "HOME";
Tooltip = "Repositories Manager";
IsActive = true;
Page = new Manager();
}
}
/// <summary>
/// Repository tab.
/// </summary>
public class RepoTab : Tab {
public RepoTab(Git.Repository repo, Dashboard page) {
Title = repo.Parent == null ? repo.Name : $"{repo.Parent.Name} : {repo.Name}";
Tooltip = repo.Path;
Repo = repo;
IsActive = false;
Page = page;
}
}
/// <summary> /// <summary>
/// Alerts. /// Alerts.
/// </summary> /// </summary>
@ -92,9 +99,8 @@ namespace SourceGit.UI {
/// Constructor /// Constructor
/// </summary> /// </summary>
public Launcher() { public Launcher() {
Tabs.Add(new ManagerTab());
InitializeComponent(); InitializeComponent();
openedTabs.SelectedItem = Tabs[0]; NewTab(null, null);
if (App.Setting.CheckUpdate) Task.Run(CheckUpdate); if (App.Setting.CheckUpdate) Task.Run(CheckUpdate);
} }
@ -103,9 +109,8 @@ namespace SourceGit.UI {
/// </summary> /// </summary>
/// <param name="repo"></param> /// <param name="repo"></param>
public void Open(Git.Repository repo) { public void Open(Git.Repository repo) {
for (int i = 1; i < Tabs.Count; i++) { foreach (var opened in Tabs) {
var opened = Tabs[i]; if (opened.IsRepo && opened.Repo.Path == repo.Path) {
if (opened.Repo.Path == repo.Path) {
openedTabs.SelectedItem = opened; openedTabs.SelectedItem = opened;
return; return;
} }
@ -113,11 +118,18 @@ namespace SourceGit.UI {
repo.Open(); repo.Open();
var page = new Dashboard(repo); var page = new Dashboard(repo);
var tab = new RepoTab(repo, page);
repo.SetPopupManager(page.popupManager); repo.SetPopupManager(page.popupManager);
var selected = openedTabs.SelectedItem as Tab;
if (selected != null && !selected.IsRepo) {
selected.Repo = repo;
selected.Page = page;
} else {
var tab = new Tab() { Repo = repo, Page = page };
Tabs.Add(tab); Tabs.Add(tab);
openedTabs.SelectedItem = tab; openedTabs.SelectedItem = tab;
} }
}
/// <summary> /// <summary>
/// Checking for update. /// Checking for update.
@ -148,25 +160,40 @@ namespace SourceGit.UI {
#region LAYOUT_CONTENT #region LAYOUT_CONTENT
/// <summary> /// <summary>
/// Close repository. /// Add new tab.
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void CloseRepo(object sender, RoutedEventArgs e) { private void NewTab(object sender, RoutedEventArgs e) {
var tab = new Tab() { Page = new Manager() };
Tabs.Add(tab);
openedTabs.SelectedItem = tab;
}
/// <summary>
/// Close tab.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CloseTab(object sender, RoutedEventArgs e) {
var tab = (sender as Button).DataContext as Tab; var tab = (sender as Button).DataContext as Tab;
if (tab == null || tab.Repo == null) { if (tab == null) return;
e.Handled = true;
if (Tabs.Count == 1) {
App.Current.Shutdown();
return; return;
} }
Tabs.Remove(tab);
tab.Page = null; tab.Page = null;
if (tab.IsRepo) {
tab.Repo.RemovePopup(); tab.Repo.RemovePopup();
tab.Repo.Close(); tab.Repo.Close();
tab.Repo = null; tab.Repo = null;
} }
Tabs.Remove(tab);
}
/// <summary> /// <summary>
/// Context menu for tab items. /// Context menu for tab items.
/// </summary> /// </summary>
@ -293,7 +320,7 @@ namespace SourceGit.UI {
if (item == null) return; if (item == null) return;
var tab = item.DataContext as Tab; var tab = item.DataContext as Tab;
if (tab == null || tab.Repo == null) return; if (tab == null) return;
if (Mouse.LeftButton == MouseButtonState.Pressed) { if (Mouse.LeftButton == MouseButtonState.Pressed) {
DragDrop.DoDragDrop(item, item, DragDropEffects.All); DragDrop.DoDragDrop(item, item, DragDropEffects.All);
@ -308,16 +335,11 @@ namespace SourceGit.UI {
var tabSrc = tabItemSrc.DataContext as Tab; var tabSrc = tabItemSrc.DataContext as Tab;
var tabDst = tabItemDst.DataContext as Tab; var tabDst = tabItemDst.DataContext as Tab;
if (tabDst.Repo == null) {
Tabs.Remove(tabSrc);
Tabs.Insert(1, tabSrc);
} else {
int dstIdx = Tabs.IndexOf(tabDst); int dstIdx = Tabs.IndexOf(tabDst);
Tabs.Remove(tabSrc); Tabs.Remove(tabSrc);
Tabs.Insert(dstIdx, tabSrc); Tabs.Insert(dstIdx, tabSrc);
} }
}
#endregion #endregion
#region TAB_SCROLL #region TAB_SCROLL