[Synfig-devl] Carlos Lopez : Initial trial of keyframe list. It doesn't compile.

2009-07-16 Thread Genete
Module: synfig
Branch: genete_keyframe_list
Commit: d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3
URL:
http://synfig.git.sourceforge.net/git/gitweb.cgi?p=synfig;a=commit;h=d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3

Author: Carlos Lopez 
Date:   Thu Jul 16 16:35:13 2009 +0200

Initial trial of keyframe list. It doesn't compile.

---

 .../trunk/src/gtkmm/widget_keyframe_list.cpp   |  270 
 .../trunk/src/gtkmm/widget_keyframe_list.h |  101 
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp 
b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
new file mode 100644
index 000..e0f372f
--- /dev/null
+++ b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
@@ -0,0 +1,270 @@
+/* === S Y N F I G = */
+/*!\file widget_keyframe_list.cpp
+** \brief A custom widget to manage keyframes in the timeline.
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
+** Copyright (c) 2009 Carlos López
+**
+** This package 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 package 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.
+** \endlegal
+*/
+/* = */
+
+/* === H E A D E R S === */
+
+#ifdef USING_PCH
+#  include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#  include 
+#endif
+
+#include "widget_keyframe_list.h"
+#include "app.h"
+#include 
+#include 
+#include 
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G === */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S = */
+
+/* === G L O B A L S === */
+
+/* === P R O C E D U R E S = */
+
+/* === M E T H O D S === */
+
+Widget_Keyframe_List::Widget_Keyframe_List():
+   editable_(false)
+{
+   set_size_request(-1,64);
+   signal_expose_event().connect(sigc::mem_fun(*this, 
&studio::Widget_Keyframe_List::redraw));
+   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
+   add_events(Gdk::BUTTON1_MOTION_MASK);
+
+}
+
+Widget_Keyframe_List::~Widget_Keyframe_List()
+{
+}
+
+bool
+Widget_Gradient::redraw(GdkEventExpose */*bleh*/)
+{
+   const int h(get_height());
+   const int w(get_width());
+
+   Glib::RefPtr gc(Gdk::GC::create(get_window()));
+   Gdk::Rectangle area(0,0,w,h);
+   if(!editable_)
+   {
+   return true;
+   }
+
+   gc->set_rgb_fg_color(Gdk::Color("#7f7f7f"));
+   get_window()->draw_rectangle(gc, false, 0, 0, w, h);
+
+   KeyframeList::iterator iter,selected_iter;
+   bool show_selected(false);
+   for(iter=kf_list_.begin();iter!=kf_list_.end();iter++)
+   {
+   if(*iter!=selected_kf)
+   get_style()->paint_arrow(
+   get_window(),
+   
(*iter==selected_kf)?Gtk::STATE_SELECTED:Gtk::STATE_ACTIVE,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   int(iter->get_time()*w)-h/2+1, /// to be fixed
+   0,
+   h,
+   h
+   );
+   else
+   {
+   selected_iter=iter;
+   show_selected=true;
+   }
+   }
+
+   // we do this so that we can be sure that
+   // the selected marker is shown on top
+   if(show_selected)
+   {
+   get_style()->paint_arrow(
+   get_window(),
+   Gtk::STATE_SELECTED,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   round_to_int(selected_iter->get_time()*w)-h/2+1,
+   0,
+   h,
+   h
+   );
+   }
+
+   return true;
+}
+
+

[Synfig-devl] Carlos Lopez : Initial trial of keyframe list. It doesn't compile.

2009-07-18 Thread Konstantin Dmitriev
Module: synfig
Branch: morevna
Commit: d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3
URL:
http://synfig.git.sourceforge.net/git/gitweb.cgi?p=synfig;a=commit;h=d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3

Author: Carlos Lopez 
Date:   Thu Jul 16 16:35:13 2009 +0200

Initial trial of keyframe list. It doesn't compile.

---

 .../trunk/src/gtkmm/widget_keyframe_list.cpp   |  270 
 .../trunk/src/gtkmm/widget_keyframe_list.h |  101 
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp 
b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
new file mode 100644
index 000..e0f372f
--- /dev/null
+++ b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
@@ -0,0 +1,270 @@
+/* === S Y N F I G = */
+/*!\file widget_keyframe_list.cpp
+** \brief A custom widget to manage keyframes in the timeline.
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
+** Copyright (c) 2009 Carlos López
+**
+** This package 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 package 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.
+** \endlegal
+*/
+/* = */
+
+/* === H E A D E R S === */
+
+#ifdef USING_PCH
+#  include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#  include 
+#endif
+
+#include "widget_keyframe_list.h"
+#include "app.h"
+#include 
+#include 
+#include 
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G === */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S = */
+
+/* === G L O B A L S === */
+
+/* === P R O C E D U R E S = */
+
+/* === M E T H O D S === */
+
+Widget_Keyframe_List::Widget_Keyframe_List():
+   editable_(false)
+{
+   set_size_request(-1,64);
+   signal_expose_event().connect(sigc::mem_fun(*this, 
&studio::Widget_Keyframe_List::redraw));
+   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
+   add_events(Gdk::BUTTON1_MOTION_MASK);
+
+}
+
+Widget_Keyframe_List::~Widget_Keyframe_List()
+{
+}
+
+bool
+Widget_Gradient::redraw(GdkEventExpose */*bleh*/)
+{
+   const int h(get_height());
+   const int w(get_width());
+
+   Glib::RefPtr gc(Gdk::GC::create(get_window()));
+   Gdk::Rectangle area(0,0,w,h);
+   if(!editable_)
+   {
+   return true;
+   }
+
+   gc->set_rgb_fg_color(Gdk::Color("#7f7f7f"));
+   get_window()->draw_rectangle(gc, false, 0, 0, w, h);
+
+   KeyframeList::iterator iter,selected_iter;
+   bool show_selected(false);
+   for(iter=kf_list_.begin();iter!=kf_list_.end();iter++)
+   {
+   if(*iter!=selected_kf)
+   get_style()->paint_arrow(
+   get_window(),
+   
(*iter==selected_kf)?Gtk::STATE_SELECTED:Gtk::STATE_ACTIVE,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   int(iter->get_time()*w)-h/2+1, /// to be fixed
+   0,
+   h,
+   h
+   );
+   else
+   {
+   selected_iter=iter;
+   show_selected=true;
+   }
+   }
+
+   // we do this so that we can be sure that
+   // the selected marker is shown on top
+   if(show_selected)
+   {
+   get_style()->paint_arrow(
+   get_window(),
+   Gtk::STATE_SELECTED,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   round_to_int(selected_iter->get_time()*w)-h/2+1,
+   0,
+   h,
+   h
+   );
+   }
+
+   return true;
+}
+
+
+void
+Widge

[Synfig-devl] Carlos Lopez : Initial trial of keyframe list. It doesn't compile.

2009-07-27 Thread Genete
Module: synfig
Branch: genete_master
Commit: d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3
URL:
http://synfig.git.sourceforge.net/git/gitweb.cgi?p=synfig;a=commit;h=d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3

Author: Carlos Lopez 
Date:   Thu Jul 16 16:35:13 2009 +0200

Initial trial of keyframe list. It doesn't compile.

---

 .../trunk/src/gtkmm/widget_keyframe_list.cpp   |  270 
 .../trunk/src/gtkmm/widget_keyframe_list.h |  101 
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp 
b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
new file mode 100644
index 000..e0f372f
--- /dev/null
+++ b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
@@ -0,0 +1,270 @@
+/* === S Y N F I G = */
+/*!\file widget_keyframe_list.cpp
+** \brief A custom widget to manage keyframes in the timeline.
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
+** Copyright (c) 2009 Carlos López
+**
+** This package 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 package 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.
+** \endlegal
+*/
+/* = */
+
+/* === H E A D E R S === */
+
+#ifdef USING_PCH
+#  include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#  include 
+#endif
+
+#include "widget_keyframe_list.h"
+#include "app.h"
+#include 
+#include 
+#include 
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G === */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S = */
+
+/* === G L O B A L S === */
+
+/* === P R O C E D U R E S = */
+
+/* === M E T H O D S === */
+
+Widget_Keyframe_List::Widget_Keyframe_List():
+   editable_(false)
+{
+   set_size_request(-1,64);
+   signal_expose_event().connect(sigc::mem_fun(*this, 
&studio::Widget_Keyframe_List::redraw));
+   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
+   add_events(Gdk::BUTTON1_MOTION_MASK);
+
+}
+
+Widget_Keyframe_List::~Widget_Keyframe_List()
+{
+}
+
+bool
+Widget_Gradient::redraw(GdkEventExpose */*bleh*/)
+{
+   const int h(get_height());
+   const int w(get_width());
+
+   Glib::RefPtr gc(Gdk::GC::create(get_window()));
+   Gdk::Rectangle area(0,0,w,h);
+   if(!editable_)
+   {
+   return true;
+   }
+
+   gc->set_rgb_fg_color(Gdk::Color("#7f7f7f"));
+   get_window()->draw_rectangle(gc, false, 0, 0, w, h);
+
+   KeyframeList::iterator iter,selected_iter;
+   bool show_selected(false);
+   for(iter=kf_list_.begin();iter!=kf_list_.end();iter++)
+   {
+   if(*iter!=selected_kf)
+   get_style()->paint_arrow(
+   get_window(),
+   
(*iter==selected_kf)?Gtk::STATE_SELECTED:Gtk::STATE_ACTIVE,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   int(iter->get_time()*w)-h/2+1, /// to be fixed
+   0,
+   h,
+   h
+   );
+   else
+   {
+   selected_iter=iter;
+   show_selected=true;
+   }
+   }
+
+   // we do this so that we can be sure that
+   // the selected marker is shown on top
+   if(show_selected)
+   {
+   get_style()->paint_arrow(
+   get_window(),
+   Gtk::STATE_SELECTED,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   round_to_int(selected_iter->get_time()*w)-h/2+1,
+   0,
+   h,
+   h
+   );
+   }
+
+   return true;
+}
+
+
+void

[Synfig-devl] Carlos Lopez : Initial trial of keyframe list. It doesn't compile.

2009-08-01 Thread Genete
Module: synfig
Branch: master
Commit: d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3
URL:
http://synfig.git.sourceforge.net/git/gitweb.cgi?p=synfig;a=commit;h=d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3

Author: Carlos Lopez 
Date:   Thu Jul 16 16:35:13 2009 +0200

Initial trial of keyframe list. It doesn't compile.

---

 .../trunk/src/gtkmm/widget_keyframe_list.cpp   |  270 
 .../trunk/src/gtkmm/widget_keyframe_list.h |  101 
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp 
b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
new file mode 100644
index 000..e0f372f
--- /dev/null
+++ b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
@@ -0,0 +1,270 @@
+/* === S Y N F I G = */
+/*!\file widget_keyframe_list.cpp
+** \brief A custom widget to manage keyframes in the timeline.
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
+** Copyright (c) 2009 Carlos López
+**
+** This package 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 package 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.
+** \endlegal
+*/
+/* = */
+
+/* === H E A D E R S === */
+
+#ifdef USING_PCH
+#  include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#  include 
+#endif
+
+#include "widget_keyframe_list.h"
+#include "app.h"
+#include 
+#include 
+#include 
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G === */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S = */
+
+/* === G L O B A L S === */
+
+/* === P R O C E D U R E S = */
+
+/* === M E T H O D S === */
+
+Widget_Keyframe_List::Widget_Keyframe_List():
+   editable_(false)
+{
+   set_size_request(-1,64);
+   signal_expose_event().connect(sigc::mem_fun(*this, 
&studio::Widget_Keyframe_List::redraw));
+   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
+   add_events(Gdk::BUTTON1_MOTION_MASK);
+
+}
+
+Widget_Keyframe_List::~Widget_Keyframe_List()
+{
+}
+
+bool
+Widget_Gradient::redraw(GdkEventExpose */*bleh*/)
+{
+   const int h(get_height());
+   const int w(get_width());
+
+   Glib::RefPtr gc(Gdk::GC::create(get_window()));
+   Gdk::Rectangle area(0,0,w,h);
+   if(!editable_)
+   {
+   return true;
+   }
+
+   gc->set_rgb_fg_color(Gdk::Color("#7f7f7f"));
+   get_window()->draw_rectangle(gc, false, 0, 0, w, h);
+
+   KeyframeList::iterator iter,selected_iter;
+   bool show_selected(false);
+   for(iter=kf_list_.begin();iter!=kf_list_.end();iter++)
+   {
+   if(*iter!=selected_kf)
+   get_style()->paint_arrow(
+   get_window(),
+   
(*iter==selected_kf)?Gtk::STATE_SELECTED:Gtk::STATE_ACTIVE,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   int(iter->get_time()*w)-h/2+1, /// to be fixed
+   0,
+   h,
+   h
+   );
+   else
+   {
+   selected_iter=iter;
+   show_selected=true;
+   }
+   }
+
+   // we do this so that we can be sure that
+   // the selected marker is shown on top
+   if(show_selected)
+   {
+   get_style()->paint_arrow(
+   get_window(),
+   Gtk::STATE_SELECTED,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   round_to_int(selected_iter->get_time()*w)-h/2+1,
+   0,
+   h,
+   h
+   );
+   }
+
+   return true;
+}
+
+
+void
+Widget

[Synfig-devl] Carlos Lopez : Initial trial of keyframe list. It doesn't compile.

2009-08-18 Thread Konstantin Dmitriev
Module: synfig
Branch: zelgadis_master
Commit: d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3
URL:
http://synfig.git.sourceforge.net/git/gitweb.cgi?p=synfig;a=commit;h=d984a091f5a0cb0c903d4abfcf7a7afb57ec82e3

Author: Carlos Lopez 
Date:   Thu Jul 16 16:35:13 2009 +0200

Initial trial of keyframe list. It doesn't compile.

---

 .../trunk/src/gtkmm/widget_keyframe_list.cpp   |  270 
 .../trunk/src/gtkmm/widget_keyframe_list.h |  101 
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp 
b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
new file mode 100644
index 000..e0f372f
--- /dev/null
+++ b/synfig-studio/trunk/src/gtkmm/widget_keyframe_list.cpp
@@ -0,0 +1,270 @@
+/* === S Y N F I G = */
+/*!\file widget_keyframe_list.cpp
+** \brief A custom widget to manage keyframes in the timeline.
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+** Copyright (c) 2007 Chris Moore
+** Copyright (c) 2009 Carlos López
+**
+** This package 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 package 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.
+** \endlegal
+*/
+/* = */
+
+/* === H E A D E R S === */
+
+#ifdef USING_PCH
+#  include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+#  include 
+#endif
+
+#include "widget_keyframe_list.h"
+#include "app.h"
+#include 
+#include 
+#include 
+
+#include "general.h"
+
+#endif
+
+/* === U S I N G === */
+
+using namespace std;
+using namespace etl;
+using namespace synfig;
+using namespace studio;
+
+/* === M A C R O S = */
+
+/* === G L O B A L S === */
+
+/* === P R O C E D U R E S = */
+
+/* === M E T H O D S === */
+
+Widget_Keyframe_List::Widget_Keyframe_List():
+   editable_(false)
+{
+   set_size_request(-1,64);
+   signal_expose_event().connect(sigc::mem_fun(*this, 
&studio::Widget_Keyframe_List::redraw));
+   add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
+   add_events(Gdk::BUTTON1_MOTION_MASK);
+
+}
+
+Widget_Keyframe_List::~Widget_Keyframe_List()
+{
+}
+
+bool
+Widget_Gradient::redraw(GdkEventExpose */*bleh*/)
+{
+   const int h(get_height());
+   const int w(get_width());
+
+   Glib::RefPtr gc(Gdk::GC::create(get_window()));
+   Gdk::Rectangle area(0,0,w,h);
+   if(!editable_)
+   {
+   return true;
+   }
+
+   gc->set_rgb_fg_color(Gdk::Color("#7f7f7f"));
+   get_window()->draw_rectangle(gc, false, 0, 0, w, h);
+
+   KeyframeList::iterator iter,selected_iter;
+   bool show_selected(false);
+   for(iter=kf_list_.begin();iter!=kf_list_.end();iter++)
+   {
+   if(*iter!=selected_kf)
+   get_style()->paint_arrow(
+   get_window(),
+   
(*iter==selected_kf)?Gtk::STATE_SELECTED:Gtk::STATE_ACTIVE,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   int(iter->get_time()*w)-h/2+1, /// to be fixed
+   0,
+   h,
+   h
+   );
+   else
+   {
+   selected_iter=iter;
+   show_selected=true;
+   }
+   }
+
+   // we do this so that we can be sure that
+   // the selected marker is shown on top
+   if(show_selected)
+   {
+   get_style()->paint_arrow(
+   get_window(),
+   Gtk::STATE_SELECTED,
+   Gtk::SHADOW_OUT,
+   area,
+   *this,
+   " ",
+   Gtk::ARROW_DOWN,
+   1,
+   round_to_int(selected_iter->get_time()*w)-h/2+1,
+   0,
+   h,
+   h
+   );
+   }
+
+   return true;
+}
+
+
+voi