From 1457c748cec623149209c23efc5c181caabfd0eb Mon Sep 17 00:00:00 2001 From: Jarvis Niu Date: Sun, 28 Feb 2016 23:19:36 +0800 Subject: [PATCH] add panel show/hide --- Niv.csproj | 2 +- exe/Niv.exe | Bin 161280 -> 191488 bytes prop/AssemblyInfo.cs | 4 +- src/ButtonAnimation.cs | 6 +- src/I18N.cs | 6 +- xaml/Niv.xaml | 54 +++---- xaml/Niv.xaml.cs | 345 +++++++++++++++++++++++++++++++++++------ 7 files changed, 337 insertions(+), 80 deletions(-) diff --git a/Niv.csproj b/Niv.csproj index e06ef47..bc2a01f 100644 --- a/Niv.csproj +++ b/Niv.csproj @@ -83,7 +83,7 @@ - + About.xaml diff --git a/exe/Niv.exe b/exe/Niv.exe index 11ac5a69e44b3f1502d411acbf1d1e4d8e98ba3a..7f1f4628aee1d9492fb8eb10c939af62d72ea794 100644 GIT binary patch delta 38362 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 O4oG8r@Ke&ii~j{+o$NdS diff --git a/prop/AssemblyInfo.cs b/prop/AssemblyInfo.cs index 935bc52..e6c6f00 100644 --- a/prop/AssemblyInfo.cs +++ b/prop/AssemblyInfo.cs @@ -20,5 +20,5 @@ ResourceDictionaryLocation.SourceAssembly )] -[assembly: AssemblyVersion("0.0.2.0")] -[assembly: AssemblyFileVersion("0.0.2.0")] +[assembly: AssemblyVersion("0.0.3.0")] +[assembly: AssemblyFileVersion("0.0.3.0")] diff --git a/src/ButtonAnimation.cs b/src/ButtonAnimation.cs index 69f0b9e..b1e1b74 100644 --- a/src/ButtonAnimation.cs +++ b/src/ButtonAnimation.cs @@ -26,10 +26,10 @@ class ThemeColors private string theme; private List appliedBorders = new List(); - private double TIME_HOVER = 0.01; + private double TIME_HOVER = 0.1; private double TIME_DOWN = 0.01; - private double TIME_UP = 0.3; - private double TIME_LEAVE = 0.4; + private double TIME_UP = 0.2; + private double TIME_LEAVE = 0.3; private SolidColorBrush brush = new SolidColorBrush(); diff --git a/src/I18N.cs b/src/I18N.cs index 8114f57..75852e3 100644 --- a/src/I18N.cs +++ b/src/I18N.cs @@ -10,12 +10,12 @@ namespace Niv { - public class I18N + public class I18n { private static string cultureCode; private static Dictionary> langData = new Dictionary>(); - static I18N() + static I18n() { loadLangData(); @@ -24,7 +24,7 @@ static I18N() // cultureCode = "en-US"; // test default // cultureCode = "zh-TW"; // test none-english - // cultureCode = "zh-TW2"; // test not exist + // cultureCode = "zh-HK"; // test not exist try { diff --git a/xaml/Niv.xaml b/xaml/Niv.xaml index 9bd5d84..0022402 100644 --- a/xaml/Niv.xaml +++ b/xaml/Niv.xaml @@ -8,10 +8,10 @@ Title="<Niv>" Height="350" Width="520" WindowStartupLocation="CenterScreen" WindowState="Maximized" Icon="/Niv;component/res/Niv.ico" Loaded="window_Loaded" Closing="window_Closing"> - + - @@ -33,7 +33,7 @@ - + @@ -43,41 +43,26 @@ - - - + - - - - - - + + - - @@ -88,5 +73,20 @@ + + diff --git a/xaml/Niv.xaml.cs b/xaml/Niv.xaml.cs index 098cc83..52541d5 100644 --- a/xaml/Niv.xaml.cs +++ b/xaml/Niv.xaml.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Data; @@ -21,12 +22,15 @@ public partial class NivWindow : Window { // components private About aboutWindow = new About(); - private AnimatorJar animationjar = new AnimatorJar(); + private AnimatorJar animatorJar = new AnimatorJar(); private ButtonAnimator buttonAnimator = new ButtonAnimator(); + // delayed closing timers + Timer timerClosePage; + // layout config static double WINDOW_MIN_WIDTH = 480; - static double WINDOW_MIN_HEIGHT = 320; + static double WINDOW_MIN_HEIGHT = 360; public static int SEPARATOR_HEIGHT = 2; //public static int MESSAGE_BOX_HEIGHT = 48; public static int MARGIN_SIZE = 50; @@ -35,8 +39,21 @@ public partial class NivWindow : Window //static int AA_SCALE_THRESHHOLD = 2; //static double PROGRESS_CAP = 2; static double INFO_WIDTH = 260; + static double MENU_HEIGHT = + 40 * 3 + // menu_item + 2 * 1 + // top_border + 17 * 1 + // seprate_line + 8 * 2; // vertical_margin private string theme = "light"; + private Dictionary visibleStates = new Dictionary(); + private bool isMarginBottomExist = true; + private bool isFullscreen = false; + private bool isAutoHideToolbar = false; + private WindowState lastWindowState = WindowState.Maximized; + + private double gridHeight = 0; + private Point mousePos; #region init and exit @@ -46,6 +63,7 @@ public NivWindow() loadLanguage(); setTheme(theme); initLayout(); + initComponents(); } private void window_Loaded(object sender, RoutedEventArgs e) @@ -59,24 +77,24 @@ private void window_Closing(object sender, System.ComponentModel.CancelEventArgs private void loadLanguage() { - window.Title = I18N._("appName"); - iImageInfo.Content = I18N._("imageInfo"); - iFilename.Content = I18N._("filename"); - iSize.Content = I18N._("size"); - iResolution.Content = I18N._("resolution"); - iDate.Content = I18N._("date"); - iHelp.Content = I18N._("help"); - iAbout.Content = I18N._("about"); - iImageInfoMenu.Content = I18N._("imageInfo"); + window.Title = I18n._("appName"); + iImageInfoTitle.Content = I18n._("imageInfo"); + iFilename.Content = I18n._("filename"); + iSize.Content = I18n._("size"); + iResolution.Content = I18n._("resolution"); + iDate.Content = I18n._("date"); + iHelp.Content = I18n._("help"); + iAbout.Content = I18n._("about"); + iImageInfo.Content = I18n._("imageInfo"); // aboutWindow - aboutWindow.Title = I18N._("about"); - aboutWindow.iAppName.Content = I18N._("appName"); - aboutWindow.iDescription.Content = I18N._("description"); + aboutWindow.Title = I18n._("about"); + aboutWindow.iAppName.Content = I18n._("appName"); + aboutWindow.iDescription.Content = I18n._("description"); Version version = Assembly.GetEntryAssembly().GetName().Version; string versionString = version.Major + "." + version.Minor + "." + version.Build; - aboutWindow.iVersion.Content = I18N._("version") + ": " + versionString; - aboutWindow.iAuthor.Content = I18N._("author") + ": " + I18N._("jarvisNiu"); - aboutWindow.iOfficialWebsite.Text = I18N._("officialWebsite") + ": "; + aboutWindow.iVersion.Content = I18n._("version") + ": " + versionString; + aboutWindow.iAuthor.Content = I18n._("author") + ": " + I18n._("jarvisNiu"); + aboutWindow.iOfficialWebsite.Text = I18n._("officialWebsite") + ": "; } private void initLayout() @@ -95,12 +113,25 @@ private void initLayout() menu.Margin = new Thickness(0, 0, 0, MARGIN_SIZE); menu.Height = 0; + visibleStates[exitButton] = false; + visibleStates[container] = false; + visibleStates[toolbar] = true; + visibleStates[info] = false; + visibleStates[page] = false; + visibleStates[menu] = false; + // add animation effects to buttons - buttonAnimator.apply(btnZoom).apply(btnPrev).apply(btnNext).apply(btnAA).apply(btnMenu).apply(exitButton) + buttonAnimator.apply(btnZoom).apply(btnPrev).apply(btnNext).apply(btnSmooth).apply(btnMenu).apply(exitButton) .apply(btnDelete).apply(btnRotateLeft).apply(btnRotateRight).apply(menuAbout) .apply(menuHelp).apply(menuInfo).apply(btnCloseInfo); } + private void initComponents() + { + timerClosePage = new Timer(3000); + timerClosePage.Elapsed += timerClosePage_Elapsed; + } + private void exit() { //restoreRotation(); @@ -127,11 +158,11 @@ private void btnRotateRight_MouseUp(object sender, MouseButtonEventArgs e) private void btnDelete_MouseUp(object sender, MouseButtonEventArgs e) { + showPage(); } private void btnPrev_MouseUp(object sender, MouseButtonEventArgs e) { - } private void btnNext_MouseUp(object sender, MouseButtonEventArgs e) @@ -139,9 +170,10 @@ private void btnNext_MouseUp(object sender, MouseButtonEventArgs e) } - private void btnAA_MouseUp(object sender, MouseButtonEventArgs e) + private void btnSmooth_MouseUp(object sender, MouseButtonEventArgs e) { - + theme = theme == "dark" ? "light" : "dark"; + setTheme(theme); } private void btnZoom_MouseUp(object sender, MouseButtonEventArgs e) @@ -151,46 +183,77 @@ private void btnZoom_MouseUp(object sender, MouseButtonEventArgs e) private void btnMenu_MouseUp(object sender, MouseButtonEventArgs e) { - theme = theme == "dark" ? "light" : "dark"; - setTheme(theme); + toggleMainMenu(); } #endregion #region menu + private void menuAbout_MouseUp(object sender, MouseButtonEventArgs e) { - showWindowAbout(); - //hideMainMenu(); + aboutWindow.Show(); + hideMainMenu(); + } + + private void menuInfo_MouseUp(object sender, MouseButtonEventArgs e) + { + toggleInfo(); + hideMainMenu(); + } + + #endregion + + #region other + + private void btnCloseInfo_MouseUp(object sender, MouseButtonEventArgs e) + { + hideInfo(); } #endregion #endregion - #region life cycle - + #region utils + private void setTheme(string theme) { buttonAnimator.setTheme(theme); if (theme == "light") { - container.Background = new SolidColorBrush(Color.FromArgb(255, 250, 250, 250)); - toolbar.Background = new SolidColorBrush(Color.FromArgb(255, 220, 220, 220)); - info.Background = new SolidColorBrush(Color.FromArgb(255, 200, 200, 200)); - separator.Background = progress.Stroke = new SolidColorBrush(Color.FromArgb(255, 170, 170, 170)); - progress.Fill = new SolidColorBrush(Color.FromArgb(255, 222, 222, 222)); + container.Background = grayBrush(250); + toolbar.Background = menu.Background = iImageInfoTitle.Background = grayBrush(220); + info.Background = grayBrush(235); + separator.Background = progress.Stroke = menu.BorderBrush = menuLine.Stroke = grayBrush(170); + progress.Fill = grayBrush(222); + iHelp.Foreground = iAbout.Foreground = iImageInfo.Foreground = iImageInfoTitle.Foreground = iPage.Foreground + = iFilename.Foreground = iSize.Foreground = iResolution.Foreground = iDate.Foreground = grayBrush(48); + labelInfoFilename.Foreground = labelInfoSize.Foreground = labelInfoResolution.Foreground + = labelInfoDate.Foreground = grayBrush(0); + page.Background = grayBrush(255, 0.75); + page.BorderBrush = grayBrush(128, 0.75); + } - else + else if (theme == "dark") { - container.Background = new SolidColorBrush(Color.FromArgb(255, 64, 64, 64)); - toolbar.Background = new SolidColorBrush(Color.FromArgb(192, 32, 32, 32)); - info.Background = new SolidColorBrush(Color.FromArgb(255, 64, 64, 64)); - separator.Background = progress.Stroke = new SolidColorBrush(Color.FromArgb(192, 64, 64, 64)); - progress.Fill = new SolidColorBrush(Color.FromArgb(75, 255, 255, 255)); + container.Background = grayBrush(32); + toolbar.Background = menu.Background = grayBrush(32, 0.75); + info.Background = iImageInfoTitle.Background = grayBrush(64); + separator.Background = progress.Stroke = menu.BorderBrush = menuLine.Stroke = iFilename.Foreground + = iSize.Foreground = iResolution.Foreground = iDate.Foreground = grayBrush(64, 0.75); + progress.Fill = grayBrush(255, 0.3); + iHelp.Foreground = iAbout.Foreground = iImageInfo.Foreground = iImageInfoTitle.Foreground = iPage.Foreground + = iFilename.Foreground = iSize.Foreground = iResolution.Foreground = iDate.Foreground = grayBrush(192); + labelInfoFilename.Foreground = labelInfoSize.Foreground = labelInfoResolution.Foreground + = labelInfoDate.Foreground = grayBrush(255); + page.Background = grayBrush(64, 0.75); + page.BorderBrush = grayBrush(128, 0.75); } + else MessageBox.Show("Not supported theme: " + theme); + // button images imageRotateLeft.Source = loadResourceBitmap("icon-rotate-left.png", theme); imageRotateRight.Source = loadResourceBitmap("icon-rotate-right.png", theme); imageDelete.Source = loadResourceBitmap("icon-delete.png", theme); @@ -199,26 +262,220 @@ private void setTheme(string theme) imageSmooth.Source = loadResourceBitmap("icon-smooth-off.png", theme); imageZoom.Source = loadResourceBitmap("icon-zoom-fit.png", theme); imageMenu.Source = loadResourceBitmap("icon-menu.png", theme); + imageCloseInfo.Source = loadResourceBitmap("icon-close.png", theme); + // menu images + imageHelp.Source = loadResourceBitmap("icon-about.png", theme); + imageAbout.Source = loadResourceBitmap("icon-about.png", theme); + imageInfo.Source = loadResourceBitmap("icon-list.png", theme); } - #endregion - - #region utils private BitmapImage loadResourceBitmap(string filename, string theme) { string namespaceName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name; return new BitmapImage(new Uri("pack://application:,,,/" + namespaceName + ";component/res/theme-" + theme + "/" + filename)); } + private SolidColorBrush grayBrush(byte brightness) + { + return new SolidColorBrush(Color.FromArgb(255, brightness, brightness, brightness)); + } + + private SolidColorBrush grayBrush(byte brightness, double alpha) + { + return new SolidColorBrush(Color.FromArgb(Convert.ToByte(255 * alpha), brightness, brightness, brightness)); + } + #endregion #region ui toogle - // window About - private void showWindowAbout() + // page + private void showPage() { - aboutWindow.Show(); + visibleStates[page] = true; + animatorJar.fadeIn(page); + timerClosePage.Stop(); + timerClosePage.Start(); + } + private void hidePage() + { + visibleStates[page] = false; + animatorJar.fadeOut(page); + } + void timerClosePage_Elapsed(object sender, ElapsedEventArgs e) + { + this.Dispatcher.Invoke(new Action(delegate { + if (visibleStates[page]) hidePage(); + })); + timerClosePage.Stop(); + } + + + // info panel + private void hideInfo() + { + if (visibleStates[info]) toggleInfo(); + } + private void toggleInfo() + { + visibleStates[info] = !visibleStates[info]; + if (visibleStates[info]) + { + this.MinWidth = WINDOW_MIN_WIDTH + INFO_WIDTH; + animatorJar.translateLeftTo(container, INFO_WIDTH - MARGIN_SIZE); + animatorJar.translateLeftTo(info, 0); + } + else + { + this.MinWidth = WINDOW_MIN_WIDTH; + animatorJar.translateLeftTo(container, -MARGIN_SIZE); + animatorJar.translateLeftTo(info, -INFO_WIDTH); + } + } + + // toolbar + private void toggleToolbar() + { + if (visibleStates[toolbar]) + hideToolbar(); + else + showToolbar(); } + private void showToolbar() + { + visibleStates[toolbar] = true; + animatorJar.marginBottomTo(toolbar, MARGIN_SIZE) + .marginBottomTo(separator, 48 + MARGIN_SIZE) + .marginBottomTo(progress, 48 + MARGIN_SIZE - 1) + .fadeIn(separator).fadeIn(progress); + } + private void hideToolbar() + { + visibleStates[toolbar] = false; + + animatorJar.marginBottomTo(toolbar, MARGIN_SIZE - 48) + .marginBottomTo(separator, 0 + MARGIN_SIZE) + .marginBottomTo(progress, 0 + MARGIN_SIZE - 1) + .fadeOut(separator).fadeOut(progress); + } + + // margion bottom + public void toggleMarginBottom() + { + if (isMarginBottomExist) + { + hideMarginBottom(); + } + else + { + showMarginBottom(); + } + } + public void showMarginBottom() + { + isMarginBottomExist = true; + + animatorJar.marginTo(container, new Thickness(-MARGIN_SIZE + (visibleStates[info] ? INFO_WIDTH : 0), -MARGIN_SIZE, -MARGIN_SIZE, 0)); + animatorJar.marginBottomTo(separator, MARGIN_SIZE - SEPARATOR_HEIGHT); + animatorJar.marginBottomTo(progress, MARGIN_SIZE - SEPARATOR_HEIGHT - 1); + animatorJar.marginBottomTo(toolbar, 0); + + page.Margin = new Thickness(-1, -1, MARGIN_SIZE + 8, MARGIN_SIZE + 8); + } + public void hideMarginBottom() + { + isMarginBottomExist = false; + + animatorJar.marginTo(container, new Thickness(-MARGIN_SIZE + (visibleStates[info] ? INFO_WIDTH : 0), -MARGIN_SIZE, -MARGIN_SIZE, -MARGIN_SIZE)); + animatorJar.marginBottomTo(separator, MARGIN_SIZE * 2 - SEPARATOR_HEIGHT); + //animatorJar.marginBottomTo(progress, MARGIN_SIZE * 2 - SEPARATOR_HEIGHT - 10); + animatorJar.marginBottomTo(toolbar, MARGIN_SIZE); + + page.Margin = new Thickness(-1, -1, MARGIN_SIZE + 8, MARGIN_SIZE * 2 + 8); + } + + // fullscreen + private void toggleFullscreen() + { + if (isFullscreen) + exitFullscreen(); + else + enterFullscreen(); + } + private void enterFullscreen() + { + lastWindowState = this.WindowState; + + this.Opacity = 0; + this.WindowStyle = System.Windows.WindowStyle.None; + if (this.WindowState != System.Windows.WindowState.Normal) + this.WindowState = System.Windows.WindowState.Normal; + this.WindowState = System.Windows.WindowState.Maximized; + this.Opacity = 1; + + exitButton.Visibility = System.Windows.Visibility.Visible; + + isFullscreen = true; + isAutoHideToolbar = true; + + hideMarginBottom(); + if (mousePos.Y < gridHeight - MARGIN_SIZE && visibleStates[toolbar]) + hideToolbar(); + } + private void exitFullscreen() + { + if (!visibleStates[toolbar]) showToolbar(); + showMarginBottom(); + + this.WindowStyle = System.Windows.WindowStyle.SingleBorderWindow; + this.WindowState = lastWindowState; + + exitButton.Visibility = System.Windows.Visibility.Hidden; + + isFullscreen = false; + isAutoHideToolbar = false; + } + + // menu + private void toggleMainMenu() + { + visibleStates[menu] = !visibleStates[menu]; + if (visibleStates[menu]) + showMainMenu(); + else + hideMainMenu(); + } + private void showMainMenu() + { + visibleStates[menu] = true; + animatorJar.heightTo(menu, MENU_HEIGHT); + animatorJar.fadeIn(menu); + } + private void hideMainMenu() + { + visibleStates[menu] = false; + animatorJar.heightTo(menu, 0); + animatorJar.fadeOut(menu); + } + + private void container_SizeChanged(object sender, SizeChangedEventArgs e) + { + gridHeight = e.NewSize.Height; + } + + private void container_MouseMove(object sender, MouseEventArgs e) + { + mousePos = e.GetPosition(niv); + // auto show&hide toolbar + if (isAutoHideToolbar && e.LeftButton == MouseButtonState.Released) + { + if (mousePos.Y > gridHeight - MARGIN_SIZE && !visibleStates[toolbar]) + showToolbar(); + else if (mousePos.Y < gridHeight - MARGIN_SIZE && visibleStates[toolbar] && visibleStates[menu]) + hideToolbar(); + } + } + #endregion