[longomatch] Add base class for timelines
- From: Andoni Morales Alastruey <amorales src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [longomatch] Add base class for timelines
- Date: Sun, 18 Dec 2011 21:39:59 +0000 (UTC)
commit 1fd3fcee5474b49cc39aa4e64d9f26860fee587a
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date: Wed Nov 23 22:53:02 2011 +0100
Add base class for timelines
LongoMatch.Core/Interfaces/ITimelineNode.cs | 38 +++
LongoMatch.Core/LongoMatch.Core.mdp | 2 +
LongoMatch.Core/Makefile.am | 1 +
LongoMatch.Core/Store/GameUnit.cs | 2 +-
LongoMatch.Core/Store/Play.cs | 3 +-
LongoMatch.Core/Store/TimelineNode.cs | 119 ++++++++
LongoMatch.GUI/Gui/Base/TimeScaleBase.cs | 355 ++++++++++++++++++++++
LongoMatch.GUI/Gui/Component/TimeScale.cs | 329 ++-------------------
LongoMatch.GUI/LongoMatch.GUI.mdp | 3 +
LongoMatch.GUI/Makefile.am | 1 +
LongoMatch.GUI/gtk-gui/objects.xml | 177 ++++-------
LongoMatch.Services/Services/GameUnitsManager.cs | 4 +-
LongoMatch/LongoMatch.mdp | 36 ---
13 files changed, 615 insertions(+), 455 deletions(-)
---
diff --git a/LongoMatch.Core/Interfaces/ITimelineNode.cs b/LongoMatch.Core/Interfaces/ITimelineNode.cs
new file mode 100644
index 0000000..d0ff33d
--- /dev/null
+++ b/LongoMatch.Core/Interfaces/ITimelineNode.cs
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2011 Andoni Morales Alastruey
+//
+// 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 2 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, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using LongoMatch.Store;
+
+namespace LongoMatch.Interfaces
+{
+ public interface ITimelineNode
+ {
+ string Name {get;set;}
+ Time Start {get;set;}
+ Time Stop {get;set;}
+ uint StartFrame {get; set;}
+ uint StopFrame {get; set;}
+ bool Selected {get; set;}
+ uint CentralFrame {get;}
+ uint TotalFrames {get;}
+ uint KeyFrame {get;}
+ bool HasDrawings {get;}
+ bool HasFrame(int frame);
+ }
+}
+
diff --git a/LongoMatch.Core/LongoMatch.Core.mdp b/LongoMatch.Core/LongoMatch.Core.mdp
index 11ce898..6536d9c 100644
--- a/LongoMatch.Core/LongoMatch.Core.mdp
+++ b/LongoMatch.Core/LongoMatch.Core.mdp
@@ -72,6 +72,8 @@
<File subtype="Code" buildaction="Compile" name="Interfaces/IPlaylistWidget.cs" />
<File subtype="Code" buildaction="Compile" name="Store/GameUnit.cs" />
<File subtype="Code" buildaction="Compile" name="Store/GameUnitsList.cs" />
+ <File subtype="Code" buildaction="Compile" name="Store/TimelineNode.cs" />
+ <File subtype="Code" buildaction="Compile" name="Interfaces/ITimelineNode.cs" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
diff --git a/LongoMatch.Core/Makefile.am b/LongoMatch.Core/Makefile.am
index 69c2389..efd2da3 100644
--- a/LongoMatch.Core/Makefile.am
+++ b/LongoMatch.Core/Makefile.am
@@ -33,6 +33,7 @@ SOURCES = \
Store/Drawing.cs \
Store/GameUnit.cs \
Store/GameUnitsList.cs \
+ Store/TimelineNode.cs \
Store/HotKey.cs \
Store/MediaFile.cs \
Store/PixbufTimeNode.cs \
diff --git a/LongoMatch.Core/Store/GameUnit.cs b/LongoMatch.Core/Store/GameUnit.cs
index eaa9885..f9ce9b9 100644
--- a/LongoMatch.Core/Store/GameUnit.cs
+++ b/LongoMatch.Core/Store/GameUnit.cs
@@ -21,7 +21,7 @@ using System.Collections.Generic;
namespace LongoMatch.Store
{
[Serializable]
- public class GameUnit: List<TimeNode>
+ public class GameUnit: List<TimelineNode>
{
public GameUnit (string name)
diff --git a/LongoMatch.Core/Store/Play.cs b/LongoMatch.Core/Store/Play.cs
index baf9713..967aeef 100644
--- a/LongoMatch.Core/Store/Play.cs
+++ b/LongoMatch.Core/Store/Play.cs
@@ -24,6 +24,7 @@ using System.Linq;
using Mono.Unix;
using Gdk;
using LongoMatch.Common;
+using LongoMatch.Interfaces;
namespace LongoMatch.Store
{
@@ -33,7 +34,7 @@ namespace LongoMatch.Store
/// </summary>
[Serializable]
- public class Play : PixbufTimeNode
+ public class Play : PixbufTimeNode, ITimelineNode
{
#region Constructors
diff --git a/LongoMatch.Core/Store/TimelineNode.cs b/LongoMatch.Core/Store/TimelineNode.cs
new file mode 100644
index 0000000..928d613
--- /dev/null
+++ b/LongoMatch.Core/Store/TimelineNode.cs
@@ -0,0 +1,119 @@
+//
+// Copyright (C) 2011 Andoni Morales Alastruey
+//
+// 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 2 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, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using LongoMatch.Interfaces;
+
+namespace LongoMatch.Store
+{
+ /* FIXME: Code duplicated from Play, unfortunately we can't
+ * modify the class hierachy */
+ public class TimelineNode: TimeNode, ITimelineNode
+ {
+ public TimelineNode ()
+ {
+ }
+
+ /// <summary>
+ /// Video framerate in frames per second. This value is taken from the
+ /// video file properties and used to translate from seconds
+ /// to frames: second 100 is equivalent to frame 100*fps
+ /// </summary>
+ public uint Fps {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Start frame number
+ /// </summary>
+ public uint StartFrame {
+ get {
+ return (uint)(Start.MSeconds * Fps / 1000);
+ }
+ set {
+ Start = new Time {MSeconds = (int)(1000 * value / Fps)};
+ }
+ }
+
+ /// <summary>
+ /// Stop frame number
+ /// </summary>
+ public uint StopFrame {
+ get {
+ return (uint)(Stop.MSeconds * Fps / 1000);
+ }
+ set {
+ Stop = new Time {MSeconds = (int)(1000 * value / Fps)};
+ }
+ }
+
+ /// <summary>
+ /// Get/Set wheter this play is actually loaded. Used in <see cref="LongoMatch.Gui.Component.TimeScale">
+ /// </summary>
+ public bool Selected {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Central frame number using (stopFrame-startFrame)/2
+ /// </summary>
+ public uint CentralFrame {
+ get {
+ return StopFrame-((TotalFrames)/2);
+ }
+ }
+
+ /// <summary>
+ /// Number of frames inside the play's boundaries
+ /// </summary>
+ public uint TotalFrames {
+ get {
+ return StopFrame-StartFrame;
+ }
+ }
+
+ /// <summary>
+ /// Get the key frame number if this play as key frame drawing or 0
+ /// </summary>
+ public uint KeyFrame {
+ get {
+ return 0;
+ }
+ }
+
+ public bool HasDrawings {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Check if the frame number is inside the play boundaries
+ /// </summary>
+ /// <param name="frame">
+ /// A <see cref="System.Int32"/> with the frame number
+ /// </param>
+ /// <returns>
+ /// A <see cref="System.Boolean"/>
+ /// </returns>
+ public bool HasFrame(int frame) {
+ return (frame>=StartFrame && frame<StopFrame);
+ }
+ }
+}
+
diff --git a/LongoMatch.GUI/Gui/Base/TimeScaleBase.cs b/LongoMatch.GUI/Gui/Base/TimeScaleBase.cs
new file mode 100644
index 0000000..c2c1fa8
--- /dev/null
+++ b/LongoMatch.GUI/Gui/Base/TimeScaleBase.cs
@@ -0,0 +1,355 @@
+// TimeScale.cs
+//
+// Copyright (C) 2007-2009 Andoni Morales Alastruey
+//
+// 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 2 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, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using Cairo;
+using Gdk;
+using Gtk;
+using Pango;
+using Mono.Unix;
+using LongoMatch.Common;
+using LongoMatch.Handlers;
+using LongoMatch.Interfaces;
+using LongoMatch.Store;
+
+namespace LongoMatch.Gui.Base
+{
+
+
+ [System.ComponentModel.Category("LongoMatch")]
+ [System.ComponentModel.ToolboxItem(true)]
+ public abstract class TimeScaleBase<T>: Gtk.DrawingArea where T:ITimelineNode
+ {
+ const int SECTION_HEIGHT = 30;
+ const double ALPHA = 0.6;
+
+ uint frames;
+ uint pixelRatio=10;
+
+ Cairo.Color color;
+ List<T> list;
+
+ T candidateTN;
+ bool candidateStart;
+ bool movingLimit;
+ uint lastTime=0;
+ uint currentFrame;
+ T selected= default(T);
+
+ Menu deleteMenu;
+ Menu menu;
+ MenuItem delete;
+ Dictionary<MenuItem,T> dic;
+
+ Pango.Layout layout;
+
+ protected string elementName = "";
+ protected int cursorFrame;
+
+ public TimeScaleBase(List<T> list, uint frames)
+ {
+ this.frames = frames;
+ this.list = list;
+ this.color = new Cairo.Color(0, 0, 1);
+ this.color.A = ALPHA;
+ HeightRequest= SECTION_HEIGHT;
+ Size((int)(frames/pixelRatio),SECTION_HEIGHT);
+ Events = EventMask.PointerMotionMask | EventMask.ButtonPressMask | EventMask.ButtonReleaseMask ;
+
+ dic = new Dictionary<MenuItem, T>();
+
+ layout = new Pango.Layout(PangoContext);
+ layout.Wrap = Pango.WrapMode.Char;
+ layout.Alignment = Pango.Alignment.Left;
+
+ SetMenu();
+ }
+
+ public uint PixelRatio {
+ get {
+ return pixelRatio;
+ }
+ set {
+ pixelRatio = value;
+ Size((int)(frames/pixelRatio),SECTION_HEIGHT);
+ }
+ }
+
+ public uint CurrentFrame {
+ get {
+ return currentFrame;
+ }
+ set {
+ currentFrame = value;
+ }
+ }
+
+ public T SelectedTimeNode {
+ get {
+ return selected;
+ }
+ set {
+ selected = value;
+ }
+ }
+
+ public void AddTimeNode(T timeNode) {
+ list.Add(timeNode);
+ }
+
+ public void RemoveTimeNode(T timeNode) {
+ list.Remove(timeNode);
+ }
+
+ public void ReDraw() {
+ Gdk.Region region = GdkWindow.ClipRegion;
+ GdkWindow.InvalidateRegion(region,true);
+ GdkWindow.ProcessUpdates(true);
+ }
+
+ abstract protected void HandleTimeNodeDeleted(List<T> timenode);
+
+ abstract protected void HandleTimeNodeChanged(T timenode, Time time);
+
+ abstract protected void HandleTimeNodeSelected(T timenode);
+
+ abstract protected void AddNewTimeNode();
+
+ void SetMenu() {
+ MenuItem newTimeNode;
+
+ menu = new Menu();
+ delete = new MenuItem(Catalog.GetString("Delete ") + elementName);
+ newTimeNode = new MenuItem(Catalog.GetString("Add new ") + elementName);
+
+ menu.Append(newTimeNode);
+ menu.Append(delete);
+
+ newTimeNode.Activated += new EventHandler(OnNewTimeNode);
+
+ menu.ShowAll();
+ }
+
+ void DrawTimeNodes(Gdk.Window win) {
+ bool hasSelectedTimeNode=false;
+
+ using(Cairo.Context g = Gdk.CairoHelper.Create(win)) {
+ int height;
+ int width;
+
+ win.Resize((int)(frames/pixelRatio), Allocation.Height);
+ win.GetSize(out width, out height);
+
+ g.Operator = Operator.Over;
+
+ foreach(T tn in list) {
+ if(!tn.Equals(selected)) {
+ Cairo.Color borderColor = new Cairo.Color(color.R+0.1, color.G+0.1,color.B+0.1, 1);
+ CairoUtils.DrawRoundedRectangle(g,tn.StartFrame/pixelRatio,3,
+ tn.TotalFrames/pixelRatio,height-6,
+ SECTION_HEIGHT/7, color, borderColor);
+ }
+ else {
+ hasSelectedTimeNode = true;
+ }
+ }
+ //Then we draw the selected TimeNode over the others
+ if(hasSelectedTimeNode) {
+ Cairo.Color borderColor = new Cairo.Color(0, 0, 0, 1);
+ CairoUtils.DrawRoundedRectangle(g,selected.StartFrame/pixelRatio,3,
+ selected.TotalFrames/pixelRatio,height-6,
+ SECTION_HEIGHT/7, color, borderColor);
+ if(selected.HasDrawings) {
+ g.MoveTo(selected.KeyFrame/pixelRatio,3);
+ g.LineTo(selected.KeyFrame/pixelRatio,SECTION_HEIGHT-3);
+ g.StrokePreserve();
+ }
+ }
+ DrawLines(win,g,height,width);
+ }
+ }
+
+ void DrawLines(Gdk.Window win, Cairo.Context g, int height, int width) {
+ if(Environment.OSVersion.Platform == PlatformID.Unix) {
+ Cairo.Color color = new Cairo.Color(0,0,0);
+ CairoUtils.DrawLine(g, currentFrame/pixelRatio,0,currentFrame/pixelRatio,height,
+ 1, color);
+ CairoUtils.DrawLine(g,0 ,0, width, 0, 1, color);
+ CairoUtils.DrawLine(g,0 ,height, width, height, 1, color);
+ }
+
+ else {
+ win.DrawLine(Style.DarkGC(StateType.Normal),0,0,width,0);
+ win.DrawLine(Style.DarkGC(StateType.Normal),
+ (int)(currentFrame/pixelRatio),0,
+ (int)(currentFrame/pixelRatio),height);
+ }
+ }
+
+
+ void DrawTimeNodesName() {
+ foreach(T tn in list) {
+ layout.Width = Pango.Units.FromPixels((int)(tn.TotalFrames/pixelRatio));
+ layout.SetMarkup(tn.Name);
+ GdkWindow.DrawLayout(Style.TextGC(StateType.Normal),
+ (int)(tn.StartFrame/pixelRatio)+2, 2, layout);
+ }
+ }
+
+ void ProcessButton3(double X) {
+ cursorFrame =(int)(X*pixelRatio);
+ deleteMenu = new Menu();
+ delete.Submenu=deleteMenu;
+ dic.Clear();
+ foreach(T tn in list) {
+ //We scan all the time Nodes looking for one matching the cursor selectcio
+ //And we add them to the delete menu
+ if(tn.HasFrame(cursorFrame)) {
+ MenuItem del = new MenuItem(Catalog.GetString("Delete "+tn.Name));
+ del.Activated += new EventHandler(OnDelete);
+ deleteMenu.Append(del);
+ dic.Add(del,tn);
+ }
+ }
+ menu.ShowAll();
+ menu.Popup();
+ }
+
+ void ProcessButton1(EventButton evnt) {
+ if(lastTime != evnt.Time) {
+ candidateTN = default(T);
+ foreach(T tn in list) {
+ int pos = (int)(evnt.X*pixelRatio);
+ //Moving from the right side
+ if(Math.Abs(pos-tn.StopFrame) < 3*pixelRatio) {
+ candidateStart = false;
+ candidateTN = tn;
+ movingLimit = true;
+ GdkWindow.Cursor = new Gdk.Cursor(CursorType.SbHDoubleArrow);
+ HandleTimeNodeChanged(tn, tn.Stop);
+ ReDraw();
+ break;
+ }
+ //Moving from the left side
+ else if(Math.Abs(pos-tn.StartFrame) < 3*pixelRatio) {
+ candidateStart =true;
+ candidateTN = tn;
+ movingLimit = true;
+ GdkWindow.Cursor = new Gdk.Cursor(CursorType.SbHDoubleArrow);
+ HandleTimeNodeChanged(tn, tn.Start);
+ ReDraw();
+ break;
+ }
+ }
+ }
+ //On Double Click
+ else {
+ foreach(T tn in list) {
+ int pos = (int)(evnt.X*pixelRatio);
+ if(tn.HasFrame(pos)) {
+ HandleTimeNodeSelected(tn);
+ break;
+ }
+ }
+ }
+ }
+
+ void OnNewTimeNode(object obj, EventArgs args) {
+ AddNewTimeNode();
+ }
+
+ void OnDelete(object obj, EventArgs args) {
+ T tNode;
+ dic.TryGetValue((MenuItem)obj, out tNode);
+ if(tNode != null) {
+ var list = new List<T>();
+ list.Add(tNode);
+ HandleTimeNodeDeleted(list);
+ }
+ }
+
+ protected override bool OnExposeEvent(EventExpose evnt)
+ {
+ if(Visible) {
+ DrawTimeNodes(evnt.Window);
+ //We don't need the draw the Sections Names if we also draw the TimeNode name
+ //DrawSectionName();
+ DrawTimeNodesName();
+ }
+ return base.OnExposeEvent(evnt);
+ }
+
+ protected override bool OnMotionNotifyEvent(EventMotion evnt)
+ {
+ int pos = (int)(evnt.X*pixelRatio);
+
+ //If not moving don't do anything
+ if(!movingLimit) {
+ }
+ //Moving Start time
+ else if(candidateStart) {
+ if(candidateTN.HasDrawings && pos > 0 && pos > candidateTN.KeyFrame-10)
+ candidateTN.StartFrame = candidateTN.KeyFrame-10;
+ //Check not to go under start time nor 0
+ else if(pos > 0 && pos < candidateTN.StopFrame-10)
+ candidateTN.StartFrame = (uint)pos;
+ HandleTimeNodeChanged(candidateTN, candidateTN.Start);
+ }
+ //Moving Stop time
+ else if(!candidateStart) {
+ if(candidateTN.HasDrawings && pos < candidateTN.KeyFrame+10)
+ candidateTN.StopFrame = candidateTN.KeyFrame+10;
+ //Check not to go under start time nor 0
+ else if(pos < frames && pos > candidateTN.StartFrame+10)
+ candidateTN.StopFrame = (uint) pos;
+ HandleTimeNodeChanged(candidateTN, candidateTN.Stop);
+ }
+
+ Gdk.Region region = GdkWindow.ClipRegion;
+ GdkWindow.InvalidateRegion(region,true);
+ GdkWindow.ProcessUpdates(true);
+
+ return base.OnMotionNotifyEvent(evnt);
+ }
+
+ protected override bool OnButtonPressEvent(EventButton evnt)
+ {
+ if(evnt.Button == 1)
+ ProcessButton1(evnt);
+ // On Right button pressed
+ else if(evnt.Button == 3)
+ ProcessButton3(evnt.X);
+ lastTime = evnt.Time;
+ return base.OnButtonPressEvent(evnt);
+ }
+
+ protected override bool OnButtonReleaseEvent(EventButton evnt)
+ {
+ if(movingLimit) {
+ movingLimit = false;
+ candidateTN.Selected = false;
+ GdkWindow.Cursor = new Gdk.Cursor(CursorType.Arrow);
+ ReDraw();
+ }
+ return base.OnButtonReleaseEvent(evnt);
+ }
+ }
+}
diff --git a/LongoMatch.GUI/Gui/Component/TimeScale.cs b/LongoMatch.GUI/Gui/Component/TimeScale.cs
index 36d7601..be7f1ed 100644
--- a/LongoMatch.GUI/Gui/Component/TimeScale.cs
+++ b/LongoMatch.GUI/Gui/Component/TimeScale.cs
@@ -26,342 +26,61 @@ using Gtk;
using Pango;
using Mono.Unix;
using LongoMatch.Common;
+using LongoMatch.Gui.Base;
using LongoMatch.Handlers;
using LongoMatch.Store;
+
namespace LongoMatch.Gui.Component
{
[System.ComponentModel.Category("LongoMatch")]
[System.ComponentModel.ToolboxItem(true)]
- public class TimeScale : Gtk.DrawingArea
+ public class TimeScale : TimeScaleBase<Play>
{
- private const int SECTION_HEIGHT = 30;
- private const double ALPHA = 0.6;
-
- private uint frames;
- private uint pixelRatio=10;
-
- private object locker;
-
private Category category;
private Cairo.Color color;
- private List<Play> list;
-
- private Play candidateTN;
- private bool candidateStart;
- private bool movingLimit;
- private Play selected=null;
-
- private uint lastTime=0;
- private uint currentFrame;
-
- private Menu deleteMenu;
- private Menu menu;
- private MenuItem delete;
- private int cursorFrame;
- private Dictionary<MenuItem,Play> dic;
-
- private Pango.Layout layout;
-
+
public event NewTagAtFrameHandler NewMarkAtFrameEvent;
public event TimeNodeChangedHandler TimeNodeChanged;
public event PlaySelectedHandler TimeNodeSelected;
public event PlaysDeletedHandler TimeNodeDeleted;
- public TimeScale(Category category, List<Play> list, uint frames)
+ public TimeScale(Category category, List<Play> list, uint frames): base(list, frames)
{
this.category = category;
- this.frames = frames;
- this.list = list;
- HeightRequest= SECTION_HEIGHT;
- Size((int)(frames/pixelRatio),SECTION_HEIGHT);
- this.color = new Cairo.Color(0, 0, 1);
- this.color.A = ALPHA;
- Events = EventMask.PointerMotionMask | EventMask.ButtonPressMask | EventMask.ButtonReleaseMask ;
-
- dic = new Dictionary<MenuItem,Play>();
-
- layout = new Pango.Layout(PangoContext);
- layout.Wrap = Pango.WrapMode.Char;
- layout.Alignment = Pango.Alignment.Left;
-
- SetMenu();
- locker = new object();
- }
-
- public uint PixelRatio {
- get {
- return pixelRatio;
- }
- set {
- lock(locker) {
- pixelRatio = value;
- Size((int)(frames/pixelRatio),SECTION_HEIGHT);
- }
- }
- }
-
- public uint CurrentFrame {
- get {
- return currentFrame;
- }
- set {
- currentFrame = value;
- }
- }
-
- public Play SelectedTimeNode {
- get {
- return selected;
- }
- set {
- selected = value;
- }
+ elementName = Catalog.GetString("play");
}
public void AddPlay(Play play) {
- list.Add(play);
+ AddTimeNode(play);
}
public void RemovePlay(Play play) {
- list.Remove(play);
+ RemoveTimeNode(play);
}
- public void ReDraw() {
- Gdk.Region region = GdkWindow.ClipRegion;
- GdkWindow.InvalidateRegion(region,true);
- GdkWindow.ProcessUpdates(true);
+ override protected void HandleTimeNodeChanged(Play play, Time time) {
+ if (TimeNodeChanged != null)
+ TimeNodeChanged(play, time);
}
-
-
- private void SetMenu() {
- MenuItem newPlay;
-
- menu = new Menu();
- delete = new MenuItem(Catalog.GetString("Delete Play"));
- newPlay = new MenuItem(Catalog.GetString("Add New Play"));
-
- menu.Append(newPlay);
- menu.Append(delete);
-
- newPlay.Activated += new EventHandler(OnNewPlay);
-
- menu.ShowAll();
+
+ override protected void HandleTimeNodeSelected(Play play) {
+ if (TimeNodeSelected != null)
+ TimeNodeSelected(play);
}
-
- private void DrawTimeNodes(Gdk.Window win) {
- lock(locker) {
- bool hasSelectedTimeNode=false;
-
- using(Cairo.Context g = Gdk.CairoHelper.Create(win)) {
- int height;
- int width;
-
- win.Resize((int)(frames/pixelRatio), Allocation.Height);
- win.GetSize(out width, out height);
-
- g.Operator = Operator.Over;
-
- foreach(Play tn in list) {
- if(tn != selected) {
- Cairo.Color borderColor = new Cairo.Color(color.R+0.1, color.G+0.1,color.B+0.1, 1);
- CairoUtils.DrawRoundedRectangle(g,tn.StartFrame/pixelRatio,3,
- tn.TotalFrames/pixelRatio,height-6,
- SECTION_HEIGHT/7, color, borderColor);
- }
- else {
- hasSelectedTimeNode = true;
- }
- }
- //Then we draw the selected TimeNode over the others
- if(hasSelectedTimeNode) {
- Cairo.Color borderColor = new Cairo.Color(0, 0, 0, 1);
- CairoUtils.DrawRoundedRectangle(g,selected.StartFrame/pixelRatio,3,
- selected.TotalFrames/pixelRatio,height-6,
- SECTION_HEIGHT/7, color, borderColor);
- if(selected.HasDrawings) {
- g.MoveTo(selected.KeyFrame/pixelRatio,3);
- g.LineTo(selected.KeyFrame/pixelRatio,SECTION_HEIGHT-3);
- g.StrokePreserve();
- }
- }
- DrawLines(win,g,height,width);
- }
- }
+
+ override protected void HandleTimeNodeDeleted(List<Play> plays) {
+ if (TimeNodeDeleted != null)
+ TimeNodeDeleted(plays);
}
-
- private void DrawLines(Gdk.Window win, Cairo.Context g, int height, int width) {
- if(Environment.OSVersion.Platform == PlatformID.Unix) {
- Cairo.Color color = new Cairo.Color(0,0,0);
- CairoUtils.DrawLine(g, currentFrame/pixelRatio,0,currentFrame/pixelRatio,height,
- 1, color);
- CairoUtils.DrawLine(g,0 ,0, width, 0, 1, color);
- CairoUtils.DrawLine(g,0 ,height, width, height, 1, color);
- }
-
- else {
- win.DrawLine(Style.DarkGC(StateType.Normal),0,0,width,0);
- win.DrawLine(Style.DarkGC(StateType.Normal),
- (int)(currentFrame/pixelRatio),0,
- (int)(currentFrame/pixelRatio),height);
- }
- }
-
-
- private void DrawTimeNodesName() {
- lock(locker) {
- foreach(Play tn in list) {
- layout.Width = Pango.Units.FromPixels((int)(tn.TotalFrames/pixelRatio));
- layout.SetMarkup(tn.Name);
- GdkWindow.DrawLayout(Style.TextGC(StateType.Normal),
- (int)(tn.StartFrame/pixelRatio)+2,
- 2,layout);
- }
- }
- }
-
- private void ProcessButton3(double X) {
- cursorFrame =(int)(X*pixelRatio);
- deleteMenu = new Menu();
- delete.Submenu=deleteMenu;
- dic.Clear();
- foreach(Play tn in list) {
- //We scan all the time Nodes looking for one matching the cursor selectcio
- //And we add them to the delete menu
- if(tn.HasFrame(cursorFrame)) {
- MenuItem del = new MenuItem(Catalog.GetString("Delete "+tn.Name));
- del.Activated += new EventHandler(OnDelete);
- deleteMenu.Append(del);
- dic.Add(del,tn);
- }
- }
- menu.ShowAll();
- menu.Popup();
- }
-
- private void ProcessButton1(EventButton evnt) {
- if(lastTime != evnt.Time) {
- candidateTN = null;
- foreach(Play tn in list) {
- int pos = (int)(evnt.X*pixelRatio);
- //Moving from the right side
- if(Math.Abs(pos-tn.StopFrame) < 3*pixelRatio) {
- candidateStart = false;
- candidateTN = tn;
- movingLimit = true;
- GdkWindow.Cursor = new Gdk.Cursor(CursorType.SbHDoubleArrow);
- TimeNodeChanged(tn,tn.Stop);
- ReDraw();
- break;
- }
- //Moving from the left side
- else if(Math.Abs(pos-tn.StartFrame) < 3*pixelRatio) {
- candidateStart =true;
- candidateTN = tn;
- movingLimit = true;
- GdkWindow.Cursor = new Gdk.Cursor(CursorType.SbHDoubleArrow);
- TimeNodeChanged(tn,tn.Start);
- ReDraw();
- break;
- }
- }
- }
- //On Double Click
- else {
- foreach(Play tn in list) {
- int pos = (int)(evnt.X*pixelRatio);
- if(TimeNodeSelected!= null && tn.HasFrame(pos)) {
- TimeNodeSelected(tn);
- break;
- }
- }
- }
- }
-
- protected void OnNewPlay(object obj, EventArgs args) {
- if(NewMarkAtFrameEvent != null)
- NewMarkAtFrameEvent(category,cursorFrame);
- }
-
- protected void OnDelete(object obj, EventArgs args) {
- Play tNode;
- dic.TryGetValue((MenuItem)obj, out tNode);
- if(TimeNodeDeleted != null && tNode != null) {
- var list = new List<Play>();
- list.Add(tNode);
- TimeNodeDeleted(list);
- }
- }
-
- protected override bool OnExposeEvent(EventExpose evnt)
- {
- if(Visible) {
- DrawTimeNodes(evnt.Window);
- //We don't need the draw the Sections Names if we also draw the TimeNode name
- //DrawSectionName();
- DrawTimeNodesName();
- }
- return base.OnExposeEvent(evnt);
- }
-
- protected override bool OnMotionNotifyEvent(EventMotion evnt)
- {
- int pos = (int)(evnt.X*pixelRatio);
-
- //If not moving don't do anything
- if(!movingLimit) {
- }
- //Moving Start time
- else if(candidateStart) {
- if(candidateTN.HasDrawings && pos > 0 && pos > candidateTN.KeyFrame-10)
- candidateTN.StartFrame = candidateTN.KeyFrame-10;
- //Check not to go under start time nor 0
- else if(pos > 0 && pos < candidateTN.StopFrame-10)
- candidateTN.StartFrame = (uint)pos;
- if(TimeNodeChanged != null)
- TimeNodeChanged(candidateTN,candidateTN.Start);
- }
- //Moving Stop time
- else if(!candidateStart) {
- if(candidateTN.HasDrawings && pos < candidateTN.KeyFrame+10)
- candidateTN.StopFrame = candidateTN.KeyFrame+10;
- //Check not to go under start time nor 0
- else if(pos < frames && pos > candidateTN.StartFrame+10)
- candidateTN.StopFrame = (uint) pos;
- if(TimeNodeChanged != null)
- TimeNodeChanged(candidateTN,candidateTN.Stop);
- }
-
- Gdk.Region region = GdkWindow.ClipRegion;
- GdkWindow.InvalidateRegion(region,true);
- GdkWindow.ProcessUpdates(true);
-
- return base.OnMotionNotifyEvent(evnt);
- }
-
- protected override bool OnButtonPressEvent(EventButton evnt)
- {
- if(evnt.Button == 1)
- ProcessButton1(evnt);
- // On Right button pressed
- else if(evnt.Button == 3)
- ProcessButton3(evnt.X);
- lastTime = evnt.Time;
- return base.OnButtonPressEvent(evnt);
- }
-
- protected override bool OnButtonReleaseEvent(EventButton evnt)
- {
- if(movingLimit) {
- movingLimit = false;
- candidateTN.Selected = false;
- GdkWindow.Cursor = new Gdk.Cursor(CursorType.Arrow);
- ReDraw();
- }
- return base.OnButtonReleaseEvent(evnt);
+
+ override protected void AddNewTimeNode() {
+ if (NewMarkAtFrameEvent != null)
+ NewMarkAtFrameEvent(category, cursorFrame);
}
+
}
}
diff --git a/LongoMatch.GUI/LongoMatch.GUI.mdp b/LongoMatch.GUI/LongoMatch.GUI.mdp
index f204889..c07a70f 100644
--- a/LongoMatch.GUI/LongoMatch.GUI.mdp
+++ b/LongoMatch.GUI/LongoMatch.GUI.mdp
@@ -143,6 +143,9 @@
<File subtype="Code" buildaction="Compile" name="gtk-gui/LongoMatch.Gui.Component.GameUnitWidget.cs" />
<File subtype="Code" buildaction="Compile" name="Gui/Component/GameUnitsTagger.cs" />
<File subtype="Code" buildaction="Compile" name="gtk-gui/LongoMatch.Gui.Component.GameUnitsTagger.cs" />
+ <File subtype="Directory" buildaction="Compile" name="Gui/Base" />
+ <File subtype="Code" buildaction="Compile" name="Gui/Base/TimeScaleBase.cs" />
+ <File subtype="Directory" buildaction="Compile" name="Gui/Component" />
</Contents>
<MonoDevelop.Autotools.MakefileInfo RelativeMakefileName="../CesarPlayer/Makefile.am" RelativeConfigureInPath="../">
<BuildFilesVar Name="FILES" />
diff --git a/LongoMatch.GUI/Makefile.am b/LongoMatch.GUI/Makefile.am
index 79c9260..1a2b7be 100644
--- a/LongoMatch.GUI/Makefile.am
+++ b/LongoMatch.GUI/Makefile.am
@@ -52,6 +52,7 @@ SOURCES = \
gtk-gui/LongoMatch.Gui.MainWindow.cs \
gtk-gui/LongoMatch.Gui.Popup.CalendarPopup.cs \
gtk-gui/LongoMatch.Gui.Popup.TransparentDrawingArea.cs \
+ Gui/Base/TimeScaleBase.cs \
Gui/Component/ButtonsWidget.cs \
Gui/Component/CategoriesScale.cs \
Gui/Component/CategoriesTemplateEditor.cs \
diff --git a/LongoMatch.GUI/gtk-gui/objects.xml b/LongoMatch.GUI/gtk-gui/objects.xml
index b6f32fd..ac16f53 100644
--- a/LongoMatch.GUI/gtk-gui/objects.xml
+++ b/LongoMatch.GUI/gtk-gui/objects.xml
@@ -25,22 +25,6 @@
</itemgroup>
</signals>
</object>
- <object type="LongoMatch.Gui.Component.TimeScale" palette-category="LongoMatch" allow-children="false" base-type="Gtk.DrawingArea">
- <itemgroups>
- <itemgroup label="TimeScale Properties">
- <property name="PixelRatio" />
- <property name="CurrentFrame" />
- </itemgroup>
- </itemgroups>
- <signals>
- <itemgroup label="TimeScale Signals">
- <signal name="NewMarkAtFrameEvent" />
- <signal name="TimeNodeChanged" />
- <signal name="TimeNodeSelected" />
- <signal name="TimeNodeDeleted" />
- </itemgroup>
- </signals>
- </object>
<object type="LongoMatch.Gui.Component.TimeReferenceWidget" palette-category="LongoMatch" allow-children="false" base-type="Gtk.DrawingArea">
<itemgroups>
<itemgroup label="TimeReferenceWidget Properties">
@@ -130,61 +114,6 @@
<itemgroups />
<signals />
</object>
- <object type="LongoMatch.Gui.Component.TagsTreeView" palette-category="LongoMatch" allow-children="false" base-type="Gtk.TreeView">
- <itemgroups>
- <itemgroup label="ListTreeViewBase Properties">
- <property name="Colors" />
- </itemgroup>
- </itemgroups>
- <signals>
- <itemgroup label="ListTreeViewBase Signals">
- <signal name="TimeNodeChanged" />
- <signal name="TimeNodeSelected" />
- <signal name="TimeNodeDeleted" />
- <signal name="PlayListNodeAdded" />
- <signal name="SnapshotSeriesEvent" />
- <signal name="TagPlay" />
- <signal name="NewRenderingJob" />
- </itemgroup>
- </signals>
- </object>
- <object type="LongoMatch.Gui.Component.PlaysTreeView" palette-category="LongoMatch" allow-children="false" base-type="Gtk.TreeView">
- <itemgroups>
- <itemgroup label="ListTreeViewBase Properties">
- <property name="Colors" />
- </itemgroup>
- </itemgroups>
- <signals>
- <itemgroup label="PlaysTreeView Signals">
- <signal name="EditProperties" />
- <signal name="TimeNodeChanged" />
- <signal name="TimeNodeSelected" />
- <signal name="TimeNodeDeleted" />
- <signal name="PlayListNodeAdded" />
- <signal name="SnapshotSeriesEvent" />
- <signal name="TagPlay" />
- <signal name="NewRenderingJob" />
- </itemgroup>
- </signals>
- </object>
- <object type="LongoMatch.Gui.Component.PlayersTreeView" palette-category="LongoMatch" allow-children="false" base-type="Gtk.TreeView">
- <itemgroups>
- <itemgroup label="ListTreeViewBase Properties">
- <property name="Colors" />
- </itemgroup>
- </itemgroups>
- <signals>
- <itemgroup label="ListTreeViewBase Signals">
- <signal name="TimeNodeChanged" />
- <signal name="TimeNodeSelected" />
- <signal name="TimeNodeDeleted" />
- <signal name="PlayListNodeAdded" />
- <signal name="SnapshotSeriesEvent" />
- <signal name="TagPlay" />
- <signal name="NewRenderingJob" />
- </itemgroup>
- </signals>
- </object>
<object type="LongoMatch.Gui.Component.NotesWidget" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
<itemgroups />
<signals>
@@ -223,21 +152,6 @@
</itemgroup>
</signals>
</object>
- <object type="LongoMatch.Gui.Component.TeamTemplateEditorWidget" palette-category="General" allow-children="false" base-type="Gtk.Bin">
- <itemgroups>
- </itemgroups>
- <signals />
- </object>
- <object type="LongoMatch.Gui.Component.CategoriesTemplateEditorWidget" palette-category="General" allow-children="false" base-type="Gtk.Bin">
- <itemgroups>
- </itemgroups>
- <signals />
- </object>
- <object type="LongoMatch.Gui.Component.TemplatesEditorWidget" palette-category="General" allow-children="false" base-type="Gtk.Bin">
- <itemgroups>
- </itemgroups>
- <signals />
- </object>
<object type="LongoMatch.Gui.Component.CategoryProperties" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
<itemgroups />
<signals>
@@ -273,30 +187,6 @@
</itemgroup>
</signals>
</object>
- <object type="LongoMatch.Gui.Component.TimeLineWidget" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
- <itemgroups>
- <itemgroup label="TimeLineWidget Properties">
- <property name="CurrentFrame" />
- </itemgroup>
- </itemgroups>
- <signals>
- <itemgroup label="TimeLineWidget Signals">
- <signal name="TimeNodeChanged" />
- <signal name="TimeNodeSelected" />
- <signal name="TimeNodeDeleted" />
- <signal name="NewMarkEvent" />
- </itemgroup>
- </signals>
- </object>
- <object type="LongoMatch.Gui.Component.TemplatesEditorBase" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
- <itemgroups>
- <itemgroup label="TemplatesEditorBase Properties">
- <property name="CanExport" />
- <property name="Edited" />
- </itemgroup>
- </itemgroups>
- <signals />
- </object>
<object type="LongoMatch.Gui.Component.GameUnitsTagger" palette-category="General" allow-children="false" base-type="Gtk.Bin">
<itemgroups />
<signals>
@@ -334,4 +224,71 @@
</itemgroup>
</signals>
</object>
+ <object type="LongoMatch.Gui.Component.TimeScale" palette-category="LongoMatch" allow-children="false" base-type="Gtk.DrawingArea">
+ <itemgroups>
+ <itemgroup label="TimeScale Properties">
+ <property name="PixelRatio" />
+ <property name="CurrentFrame" />
+ </itemgroup>
+ </itemgroups>
+ <signals>
+ <itemgroup label="TimeScale Signals">
+ <signal name="NewMarkAtFrameEvent" />
+ <signal name="TimeNodeChanged" />
+ <signal name="TimeNodeSelected" />
+ <signal name="TimeNodeDeleted" />
+ </itemgroup>
+ </signals>
+ </object>
+ <object type="LongoMatch.Gui.Component.TimeLineWidget" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
+ <itemgroups>
+ <itemgroup label="TimeLineWidget Properties">
+ <property name="CurrentFrame" />
+ </itemgroup>
+ </itemgroups>
+ <signals>
+ <itemgroup label="TimeLineWidget Signals">
+ <signal name="TimeNodeChanged" />
+ <signal name="TimeNodeSelected" />
+ <signal name="TimeNodeDeleted" />
+ <signal name="NewMarkEvent" />
+ </itemgroup>
+ </signals>
+ </object>
+ <object type="LongoMatch.Gui.Base.TimeScaleBase" palette-category="LongoMatch" allow-children="false" base-type="Gtk.DrawingArea">
+ <itemgroups>
+ <itemgroup label="TimeScaleBase Properties">
+ <property name="PixelRatio" />
+ <property name="CurrentFrame" />
+ </itemgroup>
+ </itemgroups>
+ <signals />
+ </object>
+ <object type="LongoMatch.Gui.Base.TemplatesEditorWidget" palette-category="General" allow-children="false" base-type="Gtk.Bin">
+ <itemgroups>
+ <itemgroup label="TemplatesEditorBase Properties">
+ <property name="CanExport" />
+ <property name="Edited" />
+ </itemgroup>
+ </itemgroups>
+ <signals />
+ </object>
+ <object type="LongoMatch.Gui.Base.TemplatesEditorBase" palette-category="LongoMatch" allow-children="false" base-type="Gtk.Bin">
+ <itemgroups>
+ <itemgroup label="TemplatesEditorBase Properties">
+ <property name="CanExport" />
+ <property name="Edited" />
+ </itemgroup>
+ </itemgroups>
+ <signals />
+ </object>
+ <object type="LongoMatch.Gui.Component.CategoriesTemplateEditorWidget" palette-category="General" allow-children="false" base-type="Gtk.Bin">
+ <itemgroups>
+ <itemgroup label="TemplatesEditorBase Properties">
+ <property name="CanExport" />
+ <property name="Edited" />
+ </itemgroup>
+ </itemgroups>
+ <signals />
+ </object>
</objects>
\ No newline at end of file
diff --git a/LongoMatch.Services/Services/GameUnitsManager.cs b/LongoMatch.Services/Services/GameUnitsManager.cs
index 26ebdef..0a03d09 100644
--- a/LongoMatch.Services/Services/GameUnitsManager.cs
+++ b/LongoMatch.Services/Services/GameUnitsManager.cs
@@ -68,7 +68,7 @@ namespace LongoMatch.Services
}
private void StopGameUnit(GameUnit gameUnit) {
- TimeNode timeInfo;
+ TimelineNode timeInfo;
GameUnit projectGameUnit;
Time start, stop;
@@ -77,7 +77,7 @@ namespace LongoMatch.Services
start = gameUnitsStarted[gameUnit];
stop = new Time{MSeconds=(int)player.CurrentTime};
- timeInfo = new TimeNode {Start=start, Stop=stop};
+ timeInfo = new GameUnit {Start=start, Stop=stop};
gameUnit.Add(timeInfo);
gameUnitsStarted.Remove(gameUnit);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]