diff --git a/TBO/ApplicationLibrary.cs b/TBO/ApplicationLibrary.cs index 68c641e..c9d80a2 100644 --- a/TBO/ApplicationLibrary.cs +++ b/TBO/ApplicationLibrary.cs @@ -54,7 +54,6 @@ using (TBOFile tbo = new TBOFile(cmd)) Library.Add(tbo); Library.Sort(); - Library.Save(); PopulateList(); } } @@ -68,12 +67,12 @@ { pLib.RemoveAll(); int idx = 0; - foreach (LibraryTBO ltbo in Library.Tebeos) + foreach (TBOFile ltbo in Library.Tebeos) { string info = ltbo.Author; if (Library.ValidValue(ltbo.Publisher)) info = info + " (" + ltbo.Publisher + ")"; - Item i = new Item("tbo_" + idx) { Image = ltbo.Image, Text = ltbo.DisplayName, Info = info, Count = ltbo.Year == 0 ? null : ltbo.Year.ToString(), Width = pLib.Width, Top = idx * 51 }; + Item i = new Item("tbo_" + idx) { Image = ltbo.Thumbnail, Text = ltbo.DisplayName, Info = info, Count = ltbo.Year == 0 ? null : ltbo.Year.ToString(), Width = pLib.Width, Top = idx * 51 }; pLib.Add(i); i.Tag = ltbo.FilePath; i.DoClick = itTBOClick; diff --git a/TBO/ApplicationReader.cs b/TBO/ApplicationReader.cs index 3dbec9e..8072ad8 100644 --- a/TBO/ApplicationReader.cs +++ b/TBO/ApplicationReader.cs @@ -19,6 +19,7 @@ private TBOFile tbo; private int page; private Image pageImage; + private int zoomTop = -1; public ApplicationReader() { @@ -30,6 +31,7 @@ Add(btNext); cvTebeo.DoPaint = cvTebeoPaint; + cvTebeo.DoClick = cvTebeoClick; btFullscreen.DoClick = btFullscreenClick; btClose.DoClick = btCloseClick; btLib.DoClick = btLibClick; @@ -131,16 +133,55 @@ { if (tbo == null) return; - this.page = page; - if (pageImage != null) - pageImage.Dispose(); - pageImage = tbo.GetImage(page); - if (!tbo.ReadOnly) try + if (page < 0) + page = 0; + if (page >= tbo.PageCount) + page = tbo.PageCount - 1; + if (this.page != page) + { + this.page = page; + if (pageImage != null) + pageImage.Dispose(); + pageImage = tbo.GetImage(page); + if (!tbo.ReadOnly) try + { + tbo.CurrentPage = page; + tbo.SaveMetadata(); + } + catch { }; + } + zoomTop = -1; + cvTebeo.Invalidate(); + } + + private void ZoomStep() + { + if (zoomTop < 0) + zoomTop = 0; + else + { + + } + cvTebeo.Invalidate(); + } + + public override void WhenKey(Shell.Key k, bool down) + { + if (down) + switch (k) { - tbo.CurrentPage = page; - tbo.SaveMetadata(); + case Shell.Key.k_left: + case Shell.Key.k_up: + SetPage(page - 1); + break; + case Shell.Key.k_right: + case Shell.Key.k_down: + SetPage(page + 1); + break; + case Shell.Key.k_space: + ZoomStep(); + break; } - catch { }; } private void cvTebeoPaint(Graphics g, Rectangle clip) @@ -150,6 +191,11 @@ g.DrawImageKeepRatioEx(pageImage, cvTebeo.Left, cvTebeo.Top, cvTebeo.Width, cvTebeo.Height); } + private void cvTebeoClick(Control c, Event e) + { + ZoomStep(); + } + private void btFullscreenClick(Control c, Event e) { bool nfs = !Shell.FullScreen; @@ -174,20 +220,12 @@ private void btPrevClick(Control c, Event e) { - if (page > 0) - { - SetPage(page - 1); - cvTebeo.Invalidate(); - } + SetPage(page - 1); } private void btNextClick(Control c, Event e) { - if (page < tbo.PageCount - 1) - { - SetPage(page + 1); - cvTebeo.Invalidate(); - } + SetPage(page + 1); } public override string Id => ApplicationId; diff --git a/TBO/ImageWorks.cs b/TBO/ImageWorks.cs index be5e6ec..95633e2 100644 --- a/TBO/ImageWorks.cs +++ b/TBO/ImageWorks.cs @@ -24,7 +24,7 @@ return null; } - public static bool IsGray(Image i) + public static bool IsGray(this Image i) { byte[] rgb; using (Bitmap bmp = new Bitmap(i)) @@ -40,11 +40,41 @@ return true; } + public static void DrawImageKeepRatioEx(this Graphics g, Image i, int x, int y, int width, int height, float opacity = 1.0f) + { + if (opacity == 0f) + return; + int ww, hh, xx, yy; + xx = 0; + ww = width; + hh = i.Height * width / i.Width; + if (hh > height) + { + yy = 0; + hh = height; + ww = i.Width * height / i.Height; + xx = (width - ww) / 2; + } + else + yy = (height - hh) / 2; + Rectangle dst = new Rectangle(x + xx, y + yy, ww, hh); + if (opacity >= 1.0f || opacity < 0f) + g.DrawImage(i, dst); + else + { + //Draw with alpha + ColorMatrix matrix = new ColorMatrix() { Matrix33 = opacity }; + ImageAttributes attributes = new ImageAttributes(); + attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + g.DrawImage(i, dst, 0, 0, i.Width, i.Height, GraphicsUnit.Pixel, attributes); + } + } + #endregion #region Conversion - public static Bitmap To8bppGraysacle(Image i) + public static Bitmap To8bppGraysacle(this Image i) { Bitmap bmp = new Bitmap(i.Width, i.Height, PixelFormat.Format8bppIndexed); ColorPalette pal = bmp.Palette; @@ -54,7 +84,7 @@ return null; } - public static Bitmap ToBpp(Image i, PixelFormat toBPP) + public static Bitmap ToBpp(this Image i, PixelFormat toBPP) { Bitmap bmpto; using (Bitmap bmp = new Bitmap(i)) @@ -77,7 +107,7 @@ return bmpto; } - public static Bitmap ToBppGray(Image i, PixelFormat toBPP) + public static Bitmap ToBppGray(this Image i, PixelFormat toBPP) { Bitmap bmpto; using (Bitmap bmp = new Bitmap(i)) @@ -110,7 +140,7 @@ return bmpto; } - public static Bitmap ToBppGray(Image i, PixelFormat toBPP, int[] palette) + public static Bitmap ToBppGray(this Image i, PixelFormat toBPP, int[] palette) { Bitmap bmpto; using (Bitmap bmp = new Bitmap(i)) @@ -147,7 +177,7 @@ #region I/O - public static byte[] ImageJPEG(Image i, int quality) + public static byte[] ImageJPEG(this Image i, int quality) { EncoderParameters eParams = new EncoderParameters(1); eParams.Param[0] = new EncoderParameter(Encoder.Quality, quality); @@ -158,7 +188,7 @@ return ms.ToArray(); } - public static byte[] ImagePNG(Image i) + public static byte[] ImagePNG(this Image i) { if (i == null) return null; @@ -167,7 +197,7 @@ return ms.ToArray(); } - public static byte[] ImageGIF(Image i) + public static byte[] ImageGIF(this Image i) { if (i == null) return null; diff --git a/TBO/Library.cs b/TBO/Library.cs index b518788..ef02559 100644 --- a/TBO/Library.cs +++ b/TBO/Library.cs @@ -3,16 +3,13 @@ using System.Reflection; using TBO.i18n; using TBO.UI; -using XWolf.IO; namespace TBO { static class Library { public const string LIB_FOLDER = "Library"; - public const string LIB_FILE = "Library.db"; - public const string LIB_UNKNOWN = "Unknown"; - private static List lib = new List(); + private static List lib = new List(); private static string baseDir; private static bool readOnly; @@ -24,7 +21,7 @@ Directory.CreateDirectory(baseDir); } catch { readOnly = true; } - Load(); + Scan(); } public static bool ValidValue(string s) @@ -38,11 +35,6 @@ return false; } - private static string Nvl(string s, string def = LIB_UNKNOWN) - { - return ValidValue(s) ? s : def; - } - private static string MkPath(string s) { s = s.Trim(); @@ -58,66 +50,9 @@ return s; } - private static bool IncludeInLibrary(LibraryTBO tbo) + public static void Add(TBOFile tbo) { - if (readOnly) - return false; - string path = baseDir; - path = Path.Combine(path, MkPath(Nvl(tbo.Author))); - path = Path.Combine(path, MkPath(Nvl(tbo.Publisher))); - path = Path.Combine(path, MkPath(Nvl(tbo.Year.ToString()))); - try - { - Directory.CreateDirectory(path); - path = Path.Combine(path, tbo.DisplayName + ".tebeo"); - tbo.CopyTo(path); - return true; - } - catch { return false; }; - } - - #region I/O - - public static void Save() - { - string lpath = Path.Combine(baseDir, LIB_FILE); - try - { - using (FileStream fs = new FileStream(lpath, FileMode.OpenOrCreate, FileAccess.Write)) - { - fs.Position = 0; - fs.SetLength(0); - fs.WriteInt32(lib.Count); - foreach (LibraryTBO tbo in lib) - tbo.WriteTo(fs); - } - } - catch { } - } - - private static void Load() - { - string lpath = Path.Combine(baseDir, LIB_FILE); - try - { - using (FileStream fs = new FileStream(lpath, FileMode.Open, FileAccess.Read)) - { - lib.Clear(); - fs.Position = 0; - int cnt = fs.ReadInt32(); - for (int i = 0; i < cnt; i++) - lib.Add(new LibraryTBO(fs)); - } - } - catch { } - } - - #endregion - - public static void Add(TBOFile tbof) - { - LibraryTBO tbo = new LibraryTBO(tbof); - if (IncludeInLibrary(tbo)) + if (tbo.ToLibrary()) lib.Add(tbo); else UIManager.Manager.ShowError(I18n.Lang.Error_cant_add); @@ -128,7 +63,30 @@ lib.Sort((a, b) => a.Title.CompareTo(b.Title)); } - public static LibraryTBO[] Tebeos => lib.ToArray(); + #region I/O + + private static void Scan() + { + lib.Clear(); + ScanDirectory(baseDir, lib); + + } + + private static void ScanDirectory(string dir, List lib) + { + foreach (string s in Directory.GetDirectories(dir)) + ScanDirectory(s, lib); + foreach (string s in Directory.GetFiles(dir)) + { + TBOFile tbo = new TBOFile(s, true); + tbo.ToLibrary(); + lib.Add(tbo); + } + } + + #endregion + + public static TBOFile[] Tebeos => lib.ToArray(); public static string BasePath => baseDir; } } diff --git a/TBO/LibraryTBO.cs b/TBO/LibraryTBO.cs deleted file mode 100644 index 059dc32..0000000 --- a/TBO/LibraryTBO.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Drawing; -using System.IO; -using TBO.UI.tboTK; -using XWolf.IO; - -namespace TBO -{ - class LibraryTBO - { - private string path; - - public LibraryTBO(TBOFile tbo) - { - Title = tbo.Title; - Variant = tbo.Variant; - Volume = tbo.Volume; - Author = tbo.Author; - Publisher = tbo.Publisher; - Year = tbo.Year; - Comments = tbo.Comments; - Image = GenThumb(tbo); - path = tbo.FileName; - } - - public LibraryTBO(FileStream fs) - { - path = fs.ReadString(); - Title = fs.ReadString(); - Variant = fs.ReadString(); - Volume = fs.ReadString(); - Author = fs.ReadString(); - Publisher = fs.ReadString(); - Year = fs.ReadInt32(); - Comments = fs.ReadString(); - Image = Image.FromStream(new MemoryStream(fs.ReadBlock())); - } - - private Image GenThumb(TBOFile tbo) - { - Image image; - using (Image page = tbo.GetImage(0)) - { - if (page == null) - return null; - image = new Bitmap(256, 256); - using (Graphics g = Graphics.FromImage(image)) - { - g.DrawImageKeepRatioEx(page, 0, 0, image.Width, image.Height); - } - } - return image; - } - - public TBOFile Open() - { - return new TBOFile(path); - } - - #region I/O - - public void CopyTo(string newPath) - { - File.Copy(path, newPath); - path = newPath; - } - - public void WriteTo(FileStream fs) - { - string p = path; - if (p.StartsWith(Library.BasePath)) - p = p.Substring(Library.BasePath.Length + 1); - fs.WriteString(p); - fs.WriteString(Title); - fs.WriteString(Variant); - fs.WriteString(Volume); - fs.WriteString(Author); - fs.WriteString(Publisher); - fs.WriteInt32(Year); - fs.WriteString(Comments); - fs.WriteBlock(ImageWorks.ImagePNG(Image)); - } - - #endregion - - private string GetDisplayName() - { - if (Library.ValidValue(Title)) - { - string dname = Title; - if (Library.ValidValue(Variant)) - dname = dname + " (" + Variant.Trim() + ")"; - if (Library.ValidValue(Volume)) - dname = dname + " Vol." + Volume.Trim(); - return dname; - } - else return FileName; - } - - public string Title { get; } - public string Variant { get; } - public string Volume { get; } - public string Author { get; } - public string Publisher { get; } - public int Year { get; } - public string Comments { get; } - public Image Image { get; } - public string FileName => Path.GetFileNameWithoutExtension(path); - public string DisplayName => GetDisplayName(); - public string FilePath => path; - } -} diff --git a/TBO/TBO.csproj b/TBO/TBO.csproj index f1cdc9b..eb02e98 100644 --- a/TBO/TBO.csproj +++ b/TBO/TBO.csproj @@ -58,7 +58,6 @@ - @@ -71,7 +70,6 @@ - Form diff --git a/TBO/TBOFile.cs b/TBO/TBOFile.cs index 9d99cdd..80775e0 100644 --- a/TBO/TBOFile.cs +++ b/TBO/TBOFile.cs @@ -17,44 +17,40 @@ private const int FILEVERSION = 0; private const uint ENDIANMARK = 0xFEEDFACE; private const int JPEG_QUALITY = 60; + private const string UNKNOWN = "Unknown"; + private string filePath; + private string libraryPath; private FileStream fs; private long tboStart; private bool readOnly; private bool changed; private long metapos; private bool sameEndian; + private Image thumb; private List pagepos = new List(); - public TBOFile(string filePath) + public TBOFile(string filePath, bool onlyMeta = false) { - try - { - fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); - readOnly = false; - } - catch - { - try - { - fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); - readOnly = true; - } - catch { throw new Exception("No se pudo abrir ni crear el tebeo"); } - } + this.filePath = filePath; + Open(); if (fs.Length == 0) WriteHeader(); else ReadHeader(false); ReadDirectory(); ReadMetadata(); + GetLibraryPath(); + if (onlyMeta) + { + GetThumbnail(); + Close(); + } } public void Dispose() { - if (changed) - Commit(); - fs.Close(); + Close(); } #region I/O @@ -255,6 +251,39 @@ Reset(); } + public void Open() + { + if (fs != null) + return; + try + { + fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); + readOnly = false; + } + catch + { + try + { + fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); + readOnly = true; + } + catch { throw new Exception("No se pudo abrir ni crear el tebeo"); } + } + } + + /// + /// Close the file but maintains reference for opening on future operations + /// + public void Close() + { + if (fs == null) + return; + if (changed) + Commit(); + fs.Close(); + fs = null; + } + /// /// Adds an image to the TBO /// @@ -287,10 +316,17 @@ metapos = fs.Position + sizeof(int); } + /// + /// Get a page image + /// + /// Index of page + /// Image public Image GetImage(int index) { if (index < 0 || index >= pagepos.Count) return null; + if (Closed) + Open(); fs.Position = pagepos[index]; MemoryStream ms = new MemoryStream(fs.ReadBlock()); return Image.FromStream(ms); @@ -304,6 +340,93 @@ Commit(); } + #region LibraryLocation + + public bool ToLibrary() + { + try + { + bool wasOpen = !Closed; + string absLibPath = Path.Combine(Library.BasePath, libraryPath); + if (filePath == absLibPath) + return true; + if (wasOpen) + Close(); + Directory.CreateDirectory(Path.GetDirectoryName(absLibPath)); + if (filePath.StartsWith(Library.BasePath)) + File.Move(filePath, absLibPath); + else + File.Copy(filePath, absLibPath); + filePath = absLibPath; + if (wasOpen) + Open(); + return true; + } + catch { return false; } + } + + private void GetLibraryPath() + { + //if (filePath.StartsWith(Library.BasePath)) + string path = MkPath(Nvl(Author)); + path = Path.Combine(path, MkPath(Nvl(Publisher))); + path = Path.Combine(path, MkPath(Nvl(Year.ToString()))); + path = Path.Combine(path, DisplayName + ".tebeo"); + libraryPath = path; + } + + private static string MkPath(string s) + { + s = s.Trim(); + s = s.Replace("/", ""); + s = s.Replace("\\", ""); + s = s.Replace("?", ""); + s = s.Replace("*", ""); + s = s.Replace(":", ""); + s = s.Replace("\"", ""); + s = s.Replace("<", ""); + s = s.Replace(">", ""); + s = s.Replace("|", ""); + return s; + } + + private static string Nvl(string s, string def = UNKNOWN) + { + return string.IsNullOrEmpty(s) ? def : s; + } + + #endregion + + private string GetDisplayName() + { + if (Library.ValidValue(Title)) + { + string dname = Title; + if (Library.ValidValue(Variant)) + dname = dname + " (" + Variant.Trim() + ")"; + if (Library.ValidValue(Volume)) + dname = dname + " Vol." + Volume.Trim(); + return dname; + } + else return Path.GetFileNameWithoutExtension(filePath); + } + + private Image GetThumbnail() + { + if (thumb == null) + { + using (Image page = GetImage(0)) + { + if (page == null) + return null; + thumb = new Bitmap(256, 256); + using (Graphics g = Graphics.FromImage(thumb)) + g.DrawImageKeepRatioEx(page, 0, 0, thumb.Width, thumb.Height); + } + } + return thumb; + } + #region Metadata Properteis [xIO.Serializable("Titl")] @@ -330,11 +453,24 @@ [xIO.Serializable("Page")] public int CurrentPage { get; set; } + [xIO.Serializable("Lang")] + public string Language { get; set; } + + [xIO.Serializable("Sort")] + public int Sort { get; set; } + + [xIO.Serializable("Group")] + public int Group { get; set; } + #endregion public long Size => fs.Length; public int PageCount => pagepos.Count; public bool ReadOnly => readOnly; - public string FileName => fs.Name; + public string FilePath => filePath; + public string OptimalLibraryPath => libraryPath; + public string DisplayName => GetDisplayName(); + public Image Thumbnail => thumb; + public bool Closed => fs == null; } } diff --git a/TBO/UI/Shell.cs b/TBO/UI/Shell.cs index f80dc2f..3b58ee9 100644 --- a/TBO/UI/Shell.cs +++ b/TBO/UI/Shell.cs @@ -63,7 +63,7 @@ } #region Public API - public static Application GoTo(string id,params string[] commands) + public static Application GoTo(string id, params string[] commands) { Application app; if (applications.TryGetValue(id, out app)) @@ -91,6 +91,29 @@ #endregion #region UI Notifications + + public enum Key + { + k_none, + k_up, k_down, k_left, k_right, + k_space + } + + public static void NotifyKeyDown(Key k) + { + current?.WhenKey(k, true); + } + + public static void NotifyKeyUp(Key k) + { + current?.WhenKey(k, false); + } + + public static void NotifyKeyPress(char ch) + { + + } + public static void NotifyMousePos(int x, int y) { Control c = current?.Get((int)(x / BaseZoom.X), (int)(y / BaseZoom.Y), true); diff --git a/TBO/UI/Windows/Reader.Designer.cs b/TBO/UI/Windows/Reader.Designer.cs index 96eb82f..38304b8 100644 --- a/TBO/UI/Windows/Reader.Designer.cs +++ b/TBO/UI/Windows/Reader.Designer.cs @@ -34,19 +34,21 @@ // Reader // this.AllowDrop = true; - this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; - this.ClientSize = new System.Drawing.Size(1200, 692); + this.ClientSize = new System.Drawing.Size(800, 450); this.DoubleBuffered = true; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.Name = "Reader"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "TBO"; this.DragDrop += new System.Windows.Forms.DragEventHandler(this.Reader_DragDrop); this.DragEnter += new System.Windows.Forms.DragEventHandler(this.Reader_DragEnter); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Reader_Paint); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Reader_KeyDown); + this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Reader_KeyPress); + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Reader_KeyUp); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Reader_MouseDown); this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Reader_MouseMove); this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Reader_MouseUp); diff --git a/TBO/UI/Windows/Reader.cs b/TBO/UI/Windows/Reader.cs index 99b0513..77837ee 100644 --- a/TBO/UI/Windows/Reader.cs +++ b/TBO/UI/Windows/Reader.cs @@ -98,6 +98,24 @@ //} } + private Shell.Key ShellKey(Keys k) + { + switch (k) + { + case Keys.Up: + return Shell.Key.k_up; + case Keys.Down: + return Shell.Key.k_down; + case Keys.Left: + return Shell.Key.k_left; + case Keys.Right: + return Shell.Key.k_right; + case Keys.Space: + return Shell.Key.k_space; + } + return Shell.Key.k_none; + } + private void Reader_Paint(object sender, PaintEventArgs e) { Shell.Paint(e.Graphics, e.ClipRectangle); @@ -166,5 +184,20 @@ foreach (string file in files) Shell.Application.ProcessCommand(file); } + + private void Reader_KeyDown(object sender, KeyEventArgs e) + { + Shell.NotifyKeyDown(ShellKey(e.KeyCode)); + } + + private void Reader_KeyUp(object sender, KeyEventArgs e) + { + Shell.NotifyKeyUp(ShellKey(e.KeyCode)); + } + + private void Reader_KeyPress(object sender, KeyPressEventArgs e) + { + Shell.NotifyKeyPress(e.KeyChar); + } } } diff --git a/TBO/UI/Windows/Studio.cs b/TBO/UI/Windows/Studio.cs index eb448e5..daeeab9 100644 --- a/TBO/UI/Windows/Studio.cs +++ b/TBO/UI/Windows/Studio.cs @@ -123,13 +123,13 @@ } else tbo.Reset(); - tbo.Title = tbTitle.Text; - tbo.Variant = tbVar.Text; - tbo.Volume = tbVolume.Text; - tbo.Author = tbAuthor.Text; - tbo.Publisher = tbPublisher.Text; + tbo.Title = tbTitle.Text.Trim(); + tbo.Variant = tbVar.Text.Trim(); + tbo.Volume = tbVolume.Text.Trim(); + tbo.Author = tbAuthor.Text.Trim(); + tbo.Publisher = tbPublisher.Text.Trim(); tbo.Year = (int)nudYear.Value; - tbo.Comments = tbCom.Text; + tbo.Comments = tbCom.Text.Trim(); for (int i = 0; i < files.Count; i++) { pbGo.Value = i; diff --git a/TBO/UI/tboTK/Application.cs b/TBO/UI/tboTK/Application.cs index b86b4ae..95c294b 100644 --- a/TBO/UI/tboTK/Application.cs +++ b/TBO/UI/tboTK/Application.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; namespace TBO.UI.tboTK { @@ -68,16 +69,36 @@ public Control[] Controls => new List(controls.Values).ToArray(); #endregion + public virtual void WhenKey(Shell.Key k, bool down) + { + } + public abstract void ResizeTo(Size size); public virtual void Paint(Graphics g, Rectangle clip) { foreach (Control c in controls.Values) if (c.Visible && c.Clips(clip)) - c.Paint(g, clip); + PaintControl(c, g, clip); } public abstract void ProcessCommand(string cmd); public abstract void Shown(); + private void PaintControl(Control c, Graphics g, Rectangle clip) + { + g.Clip = new Region(c.ScreenBounds); + clip = new Rectangle(clip.Left - c.Left, clip.Top - c.Top, clip.Width, clip.Height); + GraphicsState gs = g.Save(); + g.TranslateTransform(c.Left, c.Top); + try + { + c.Paint(g, clip); + } + finally + { + g.Restore(gs); + } + } + public abstract string Id { get; } public abstract string Title { get; } } diff --git a/TBO/UI/tboTK/Button.cs b/TBO/UI/tboTK/Button.cs index df30079..54e368a 100644 --- a/TBO/UI/tboTK/Button.cs +++ b/TBO/UI/tboTK/Button.cs @@ -4,8 +4,8 @@ { class Button : Control { - private bool hover = false; - private bool pressed = false; + protected bool hover = false; + protected bool pressed = false; public Button(string id) : base(id) { @@ -16,9 +16,9 @@ public override void Paint(Graphics g, Rectangle clip) { if (pressed) - g.DrawImageKeepRatioEx(Image, Left + 1, Top + 1, Width - 2, Height - 2); + g.DrawImageKeepRatioEx(Image, 1, 1, Width - 2, Height - 2); else - g.DrawImageKeepRatioEx(Image, Left, Top, Width, Height, hover ? 1f : 0.5f); + g.DrawImageKeepRatioEx(Image, 0, 0, Width, Height, hover ? 1f : 0.5f); } public override void Handle(Event e) diff --git a/TBO/UI/tboTK/Control.cs b/TBO/UI/tboTK/Control.cs index 0d2a1cc..2f36bef 100644 --- a/TBO/UI/tboTK/Control.cs +++ b/TBO/UI/tboTK/Control.cs @@ -14,11 +14,42 @@ public EventDelegate DoClick; public EventDelegate DoScroll; + internal Control parent; + public Control(string id) { Id = id; } + public Rectangle BoundsToScreen(Rectangle bounds) + { + return new Rectangle(PointToScreen(bounds.Location), bounds.Size); + } + + public Point PointToScreen(Point p) + { + Control c = parent; + while (c != null) + { + p.X += c.OffsetLeft; + p.Y += c.OffsetTop; + c = c.parent; + } + return p; + } + + public Point PointToControl(Point p) + { + Control c = parent; + while (c != null) + { + p.X -= c.OffsetLeft; + p.Y -= c.OffsetTop; + c = c.parent; + } + return p; + } + public bool Clips(Rectangle clip) { return Bounds.IntersectsWith(clip); @@ -61,16 +92,20 @@ public void Invalidate() { - Shell.Invalidate(new Rectangle(Left, Top, Width, Height)); + Shell.Invalidate(ScreenBounds); } public string Id { get; } public int Top { get; set; } public int Left { get; set; } + internal virtual int OffsetTop => Top; + internal virtual int OffsetLeft => Left; public int Width { get; set; } public int Height { get; set; } public bool Visible { get; set; } = true; public Rectangle Bounds => new Rectangle(Left, Top, Width, Height); + public Rectangle ScreenBounds => BoundsToScreen(Bounds); public object Tag { get; set; } + public Control Parent => parent; } } diff --git a/TBO/UI/tboTK/Item.cs b/TBO/UI/tboTK/Item.cs index f491af9..4078dfa 100644 --- a/TBO/UI/tboTK/Item.cs +++ b/TBO/UI/tboTK/Item.cs @@ -1,5 +1,4 @@ using System.Drawing; -using System.Drawing.Drawing2D; using System.Drawing.Text; namespace TBO.UI.tboTK @@ -10,16 +9,15 @@ private Brush fg = new SolidBrush(Color.Black); private Brush fgInfo = new SolidBrush(Color.Gray); private Brush bg = new SolidBrush(Color.FromArgb(200, 255, 255, 255)); + private Brush bghover = new SolidBrush(Color.FromArgb(255, 255, 255, 255)); public Item(string id) : base(id) { } public override void Paint(Graphics g, Rectangle clip) { - g.Clip = new Region(Bounds); g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; - g.FillRectangle(bg, Bounds); - GraphicsState gs = g.Save(); - g.TranslateTransform(Left, Top); + g.FillRectangle(hover ? bghover : bg, new Rectangle(0, 0, Width, Height)); + if (Image != null) g.DrawImageKeepRatioEx(Image, 0, 0, Height, Height); SizeF stitle = g.MeasureString(Text, fnt); @@ -36,7 +34,6 @@ g.DrawString(Count, fnt, fgInfo, (Left + Width - scount.Width) - 5, ((Height - stitle.Height) / 2) + 10); } - g.Restore(gs); } public string Text { get; set; } diff --git a/TBO/UI/tboTK/Panel.cs b/TBO/UI/tboTK/Panel.cs index a6139ee..4543830 100644 --- a/TBO/UI/tboTK/Panel.cs +++ b/TBO/UI/tboTK/Panel.cs @@ -22,6 +22,7 @@ if (controls.ContainsKey(c.Id)) return false; controls[c.Id] = c; + c.parent = this; Invalidate(); return true; } @@ -40,6 +41,8 @@ public Control Get(int x, int y, bool deep = false) { + x -= Left + scrollOffset.X; + y -= Top + scrollOffset.Y; Control result = null; foreach (Control c in controls.Values) { @@ -64,11 +67,18 @@ { if (c == null) return false; - return controls.Remove(c.Id); + if (controls.Remove(c.Id)) + { + c.parent = null; + return true; + } + return false; } public void RemoveAll() { + foreach (Control c in controls.Values) + c.parent = null; controls.Clear(); Invalidate(); } @@ -78,13 +88,22 @@ public override void Paint(Graphics g, Rectangle clip) { - //g.FillRectangle(new SolidBrush(Color.Wheat), Left, Top, Width, Height); - // g.SetClip(new Rectangle(Left, Top, Width, Height)); GraphicsState gs = g.Save(); - g.TranslateTransform(Left - scrollOffset.X, Top - scrollOffset.Y); + g.TranslateTransform(-scrollOffset.X, -scrollOffset.Y); foreach (Control c in controls.Values) if (c.Clips(clip)) - c.Paint(g, clip); + { + GraphicsState gsc = g.Save(); + g.TranslateTransform(c.Left, c.Top); + try + { + c.Paint(g, clip); + } + finally + { + g.Restore(gsc); + } + } g.Restore(gs); } diff --git a/TBO/UI/tboTK/UIExtension.cs b/TBO/UI/tboTK/UIExtension.cs deleted file mode 100644 index 98da41e..0000000 --- a/TBO/UI/tboTK/UIExtension.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Drawing; -using System.Drawing.Imaging; - -namespace TBO.UI.tboTK -{ - static class UIExtension - { - public static void DrawImageKeepRatioEx(this Graphics g, Image i, int x, int y, int width, int height, float opacity = 1.0f) - { - if (opacity == 0f) - return; - int ww, hh, xx, yy; - xx = 0; - ww = width; - hh = i.Height * width / i.Width; - if (hh > height) - { - yy = 0; - hh = height; - ww = i.Width * height / i.Height; - xx = (width - ww) / 2; - } - else - yy = (height - hh) / 2; - Rectangle dst = new Rectangle(x + xx, y + yy, ww, hh); - if (opacity >= 1.0f || opacity < 0f) - g.DrawImage(i, dst); - else - { - //Draw with alpha - ColorMatrix matrix = new ColorMatrix() { Matrix33 = opacity }; - ImageAttributes attributes = new ImageAttributes(); - attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - g.DrawImage(i, dst, 0, 0, i.Width, i.Height, GraphicsUnit.Pixel, attributes); - } - } - } -}