// ZoomBar.cs created with MonoDevelop
// User: klose at 13:48 16.12.2008
// CVS release: $Id: ZoomBar.cs,v 1.14 2010-11-25 13:52:56 klose Exp $
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2009  Thomas Klose, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;

using Gtk;


namespace Hiperscan.QuickStep.Zoombar
{

    public class HZoombar : Hiperscan.QuickStep.Zoombar.Zoombar
    {
        
        protected static Style scrollbar_style;

        public HZoombar() : base(0f, 0f, 1f, 0f)
        {
            this.Name = "Horizontal Zoom Bar";

            Arrow arrow;
            HBox  hb;

            // center handle
            Alignment align = new Alignment(0.5f, 0.5f, 1.0f, 0.7f); 
            hb = new HBox();
            HBox hb2 = new HBox();
            hb.Spacing = 3;
            hb2.PackStart(hb, true, false, 0);
            
            for (int ix=1; ix < 4; ++ix)
            {
                hb.PackStart(new VSlideSeparator());
            }
            align.Add(hb2);
            this.buttons[2].Add(align);

            // first handle
            hb = new HBox();
            arrow = new Arrow(ArrowType.Left, ShadowType.In);
            hb.PackStart(arrow, true, true, 0);
            arrow = new Arrow(ArrowType.Right, ShadowType.In);
            hb.PackStart(arrow, true, true, 0);
            this.buttons[3].Add(hb);

            // right handle
            hb = new HBox();
            arrow = new Arrow(ArrowType.Left, ShadowType.In);
            hb.PackStart(arrow, true, true, 0);
            arrow = new Arrow(ArrowType.Right, ShadowType.In);
            hb.PackStart(arrow, true, true, 0);
            this.buttons[4].Add(hb);

            // scroll buttons
            arrow = new Arrow(ArrowType.Left, ShadowType.In);
            this.buttons[5].Add(arrow);
            
            arrow = new Arrow(ArrowType.Right, ShadowType.In);
            this.buttons[6].Add(arrow);
            
            this.frame.ScrollEvent += this.OnScrollEvent;

            this.ModifyStyle();
            this.StyleSet += (o, args) =>
            {
                HZoombar.scrollbar_style = null;
                this.ModifyStyle();
            };
            
            // update geometry
            this.Update();
        }
        
        private void ModifyStyle()
        {
            Style style = this.GetScrollbarStyle();
            if (style == null)
                return;
            foreach (ZoomBarButton b in this.buttons)
            {
                b.Style = style;
            }
        }
        
        private Style GetScrollbarStyle()
        {
            if (HZoombar.scrollbar_style == null)
            {
                HScrollbar sb = new HScrollbar(new Adjustment(0f, 1f, 1f, 0.1f, 0.2f, 0f));
                HZoombar.scrollbar_style = Rc.GetStyle(sb);
                int w = sb.SizeRequest().Height;
                
                if (w > 4)
                    this.width = (w % 2 == 1) ? w : w+1;

                if (Settings.Default.ThemeName == "New Wave")
                    HZoombar.scrollbar_style = Rc.GetStyle(new Button());

                if (Settings.Default.ThemeName == "Adwaita")
                {
                    HZoombar.scrollbar_style = Rc.GetStyle(new Button());
                    this.width = 19;
                }
            }
            
            return HZoombar.scrollbar_style;
        }
        
        protected override void Update()
        {                        
            int pl  = this.frame_width; 
            int pw  = this.Width;

            this.CalculateGeomParams(pl, pw);

            if (l < 0 || w < 0 || offset < 0)
                return; // invalid data -> do nothing
            
            this.buttons[0].WidthRequest  = (int)Math.Round(offset);
            this.buttons[0].HeightRequest = (int)Math.Round(w);
            this.buttons[1].WidthRequest  = (int)Math.Round(lmax - l - offset);
            this.buttons[1].HeightRequest = (int)Math.Round(w);
            this.buttons[2].WidthRequest  = (int)Math.Round(l); // - 2*Defaults.HandleLength);
            this.buttons[2].HeightRequest = (int)Math.Round(w);
            this.buttons[3].WidthRequest  = (int)Math.Round(Defaults.HandleLength);
            this.buttons[3].HeightRequest = (int)Math.Round(w);
            this.buttons[4].WidthRequest  = (int)Math.Round(Defaults.HandleLength);
            this.buttons[4].HeightRequest = (int)Math.Round(w);
            this.buttons[5].WidthRequest  = (int)Math.Round(Defaults.ButtonLength);
            this.buttons[5].HeightRequest = (int)Math.Round(w);
            this.buttons[6].WidthRequest  = (int)Math.Round(Defaults.ButtonLength);
            this.buttons[6].HeightRequest = (int)Math.Round(w);
    
            this.Move(this.buttons[0], (int)Math.Round(Defaults.ButtonLength), 0);
            this.Move(this.buttons[1], (int)Math.Round(Defaults.ButtonLength + offset + l), 0);
            this.Move(this.buttons[2], (int)Math.Round(Defaults.ButtonLength + offset), 0); // + Defaults.HandleLength), 0);
            this.Move(this.buttons[3], (int)Math.Round(Defaults.ButtonLength + offset), 0);
            this.Move(this.buttons[4], (int)Math.Round(Defaults.ButtonLength + l + offset - Defaults.HandleLength), 0);
            this.Move(this.buttons[5], 0, 0);
            this.Move(this.buttons[6], (int)Math.Round(Defaults.ButtonLength + lmax), 0);
            
            if (Math.Abs(zoom - 1.0) < EPSILON || Math.Abs(pan) < EPSILON)
                this.buttons[5].Sensitive = false;
            else
                 this.buttons[5].Sensitive = true;
                        
            if (Math.Abs(zoom - 1.0) < EPSILON || Math.Abs(pan - 1.0) < EPSILON)
                this.buttons[6].Sensitive = false;
            else
                this.buttons[6].Sensitive = true;

            this.SetSizeRequest((int)(lmin + 2*Defaults.ButtonLength + 10), pw);

            // execute event handlers
            this.ChangeNotify(this.dragging == false);
        }
        
        private void OnScrollEvent(object o, ScrollEventArgs e)
        {
            double pan_step = scroll_step/(zoom-1);

            if (e.Event.Direction == Gdk.ScrollDirection.Up||
                e.Event.Direction == Gdk.ScrollDirection.Right)
            {
                if (pan + pan_step <= 1.0)
                    pan += pan_step;
                else
                    pan = 1.0;
            }
            else
            {
                if (pan - pan_step >= 0.0)
                    pan -= pan_step;
                else
                    pan = 0.0;
            }            
            this.Update();
        }
    }        
}