Merge branch 'master' of git://git.lumiera.org/LUMIERA
This commit is contained in:
commit
06504c7b04
21 changed files with 954 additions and 264 deletions
75
SConstruct
75
SConstruct
|
|
@ -61,7 +61,7 @@ def setupBasicEnvironment():
|
|||
opts = defineCmdlineOptions()
|
||||
env = LumieraEnvironment(options=opts
|
||||
,toolpath = [TOOLDIR]
|
||||
,tools = ["default", "BuilderGCH"]
|
||||
,tools = ["default", "BuilderGCH", "BuilderDoxygen"]
|
||||
)
|
||||
|
||||
env.Append ( CCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honor CFLAGS, only CCFLAGS
|
||||
|
|
@ -173,24 +173,21 @@ def configurePlatform(env):
|
|||
# run all configuration checks in the given env
|
||||
|
||||
# Perform checks for prerequisites --------------------------------------------
|
||||
problems = []
|
||||
if not conf.TryAction('pkg-config --version > $TARGET')[0]:
|
||||
print 'We need pkg-config for including library configurations, exiting.'
|
||||
Exit(1)
|
||||
problems.append('We need pkg-config for including library configurations, exiting.')
|
||||
|
||||
if not conf.CheckLibWithHeader('m', 'math.h','C'):
|
||||
print 'Did not find math.h / libm, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Did not find math.h / libm.')
|
||||
|
||||
if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'):
|
||||
print 'Functions for runtime dynamic loading not available, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Functions for runtime dynamic loading not available.')
|
||||
|
||||
if not conf.CheckLibWithHeader('nobugmt', 'nobug.h', 'C'):
|
||||
print 'Did not find NoBug [http://www.pipapo.org/pipawiki/NoBug], exiting.'
|
||||
Exit(1)
|
||||
problems.append('Did not find NoBug [http://www.pipapo.org/pipawiki/NoBug].')
|
||||
|
||||
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'):
|
||||
print 'Did not find the pthread lib or pthread.h, exiting.'
|
||||
problems.append('Did not find the pthread lib or pthread.h.')
|
||||
else:
|
||||
conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD')
|
||||
conf.env.Append(CCFLAGS = ' -pthread')
|
||||
|
|
@ -202,57 +199,56 @@ def configurePlatform(env):
|
|||
conf.env.Append(CPPFLAGS = ' -DHAS_VALGRIND_VALGIND_H')
|
||||
|
||||
if not conf.CheckCXXHeader('tr1/memory'):
|
||||
print 'We rely on the std::tr1 proposed standard extension for shared_ptr.'
|
||||
Exit(1)
|
||||
problems.append('We rely on the std::tr1 proposed standard extension for shared_ptr.')
|
||||
|
||||
if not conf.CheckCXXHeader('boost/config.hpp'):
|
||||
print 'We need the C++ boost-lib.'
|
||||
Exit(1)
|
||||
problems.append('We need the C++ boost-lib.')
|
||||
else:
|
||||
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
|
||||
print 'We need boost::shared_ptr (shared_ptr.hpp).'
|
||||
Exit(1)
|
||||
problems.append('We need boost::shared_ptr (shared_ptr.hpp).')
|
||||
if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'):
|
||||
print 'We need boost::program_options (including binary lib for linking).'
|
||||
Exit(1)
|
||||
problems.append('We need boost::program_options (including binary lib for linking).')
|
||||
if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'):
|
||||
print 'We need the boost regular expression lib (incl. binary lib for linking).'
|
||||
Exit(1)
|
||||
problems.append('We need the boost regular expression lib (incl. binary lib for linking).')
|
||||
|
||||
# if not conf.CheckLibWithHeader('gavl', ['gavlconfig.h', 'gavl/gavl.h'], 'C'):
|
||||
|
||||
if not conf.CheckPkgConfig('gavl', 1.0):
|
||||
print 'Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html], exiting.'
|
||||
Exit(1)
|
||||
problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].')
|
||||
else:
|
||||
conf.env.mergeConf('gavl')
|
||||
|
||||
if not conf.CheckPkgConfig('gtkmm-2.4', 2.8):
|
||||
print 'Unable to configure GTK--, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Unable to configure GTK--, exiting.')
|
||||
|
||||
if not conf.CheckPkgConfig('glibmm-2.4', '2.16'):
|
||||
print 'Unable to configure Lib glib--, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Unable to configure Lib glib--, exiting.')
|
||||
|
||||
if not conf.CheckPkgConfig('cairomm-1.0', 0.6):
|
||||
print 'Unable to configure Cairo--, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Unable to configure Cairo--, exiting.')
|
||||
|
||||
if not conf.CheckPkgConfig('gdl-1.0', '0.6.1'):
|
||||
print 'Unable to configure the GNOME DevTool Library, exiting.'
|
||||
Exit(1)
|
||||
problems.append('Unable to configure the GNOME DevTool Library, exiting.')
|
||||
|
||||
if not conf.CheckPkgConfig('librsvg-2.0', '2.18.1'):
|
||||
print 'Need rsvg Library for rendering icons.'
|
||||
Exit(1)
|
||||
problems.append('Need rsvg Library for rendering icons.')
|
||||
|
||||
if not conf.CheckPkgConfig('xv'): Exit(1)
|
||||
if not conf.CheckPkgConfig('xv'): problems.append('Need lib xv')
|
||||
# if not conf.CheckPkgConfig('xext'): Exit(1)
|
||||
# if not conf.CheckPkgConfig('sm'): Exit(1)
|
||||
#
|
||||
# obviously not needed?
|
||||
|
||||
|
||||
# report missing dependencies
|
||||
if problems:
|
||||
print "*** unable to build due to the following problems:"
|
||||
for isue in problems:
|
||||
print " * %s" % isue
|
||||
print
|
||||
print "build aborted."
|
||||
Exit(1)
|
||||
|
||||
print "** Gathered Library Info: %s" % conf.env.libInfo.keys()
|
||||
|
||||
|
||||
|
|
@ -340,16 +336,9 @@ def definePostBuildTargets(env, artifacts):
|
|||
env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ])
|
||||
env.Clean ('build', [ '$SRCDIR/pre.gch' ])
|
||||
|
||||
# Doxygen documentation
|
||||
# Note: at the moment we only depend on Doxyfile
|
||||
# obviousely, we should depend on all sourcefiles
|
||||
# real Doxygen builder for scons is under developement for 0.97
|
||||
# so for the moment I prefere not to bother
|
||||
doxyfile = File('doc/devel/Doxyfile')
|
||||
env.NoClean(doxyfile)
|
||||
doxydoc = artifacts['doxydoc'] = [ Dir('doc/devel/html'), Dir('doc/devel/latex') ]
|
||||
env.Command(doxydoc, doxyfile, "doxygen Doxyfile 2>&1 |tee ,doxylog", chdir='doc/devel')
|
||||
env.Clean ('doc/devel', doxydoc + ['doc/devel/,doxylog'])
|
||||
doxydoc = artifacts['doxydoc'] = env.Doxygen('doc/devel/Doxyfile')
|
||||
env.Alias ('doxydoc', doxydoc)
|
||||
env.Clean ('doxydoc', doxydoc + ['doc/devel/,doxylog','doc/devel/warnings.txt'])
|
||||
|
||||
|
||||
def defineInstallTargets(env, artifacts):
|
||||
|
|
|
|||
230
admin/scons/BuilderDoxygen.py
Normal file
230
admin/scons/BuilderDoxygen.py
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
# -*- python -*-
|
||||
##
|
||||
## BuilderDoxygen.py - SCons builder for generating Doxygen documentation
|
||||
##
|
||||
|
||||
#
|
||||
# Astxx, the Asterisk C++ API and Utility Library.
|
||||
# Copyright (C) 2005, 2006 Matthew A. Nicholson
|
||||
# Copyright (C) 2006 Tim Blechmann
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License version 2.1 as published by the Free Software Foundation.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library; if not, see http://www.gnu.org/licenses/
|
||||
#####################################################################
|
||||
|
||||
# history: 8/2008 adapted for Lumiera build system
|
||||
# added patch for Doxyfile in subdirectory
|
||||
# see http://www.scons.org/wiki/DoxygenBuilder
|
||||
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import glob
|
||||
from fnmatch import fnmatch
|
||||
|
||||
|
||||
def DoxyfileParse(file_contents):
|
||||
"""
|
||||
Parse a Doxygen source file and return a dictionary of all the values.
|
||||
Values will be strings and lists of strings.
|
||||
"""
|
||||
data = {}
|
||||
|
||||
import shlex
|
||||
lex = shlex.shlex(instream = file_contents, posix = True)
|
||||
lex.wordchars += "*+./-:"
|
||||
lex.whitespace = lex.whitespace.replace("\n", "")
|
||||
lex.escape = ""
|
||||
|
||||
lineno = lex.lineno
|
||||
token = lex.get_token()
|
||||
key = token # the first token should be a key
|
||||
last_token = ""
|
||||
key_token = False
|
||||
next_key = False
|
||||
new_data = True
|
||||
|
||||
def append_data(data, key, new_data, token):
|
||||
if new_data or len(data[key]) == 0:
|
||||
data[key].append(token)
|
||||
else:
|
||||
data[key][-1] += token
|
||||
|
||||
while token:
|
||||
if token in ['\n']:
|
||||
if last_token not in ['\\']:
|
||||
key_token = True
|
||||
elif token in ['\\']:
|
||||
pass
|
||||
elif key_token:
|
||||
key = token
|
||||
key_token = False
|
||||
else:
|
||||
if token == "+=":
|
||||
if not data.has_key(key):
|
||||
data[key] = list()
|
||||
elif token == "=":
|
||||
data[key] = list()
|
||||
else:
|
||||
append_data( data, key, new_data, token )
|
||||
new_data = True
|
||||
|
||||
last_token = token
|
||||
token = lex.get_token()
|
||||
|
||||
if last_token == '\\' and token != '\n':
|
||||
new_data = False
|
||||
append_data( data, key, new_data, '\\' )
|
||||
|
||||
# compress lists of len 1 into single strings
|
||||
for (k, v) in data.items():
|
||||
if len(v) == 0:
|
||||
data.pop(k)
|
||||
|
||||
# items in the following list will be kept as lists and not converted to strings
|
||||
if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]:
|
||||
continue
|
||||
|
||||
if len(v) == 1:
|
||||
data[k] = v[0]
|
||||
|
||||
return data
|
||||
|
||||
def DoxySourceScan(node, env, path):
|
||||
"""
|
||||
Doxygen Doxyfile source scanner. This should scan the Doxygen file and add
|
||||
any files used to generate docs to the list of source files.
|
||||
"""
|
||||
default_file_patterns = [
|
||||
'*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx',
|
||||
'*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++',
|
||||
'*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm',
|
||||
'*.py',
|
||||
]
|
||||
|
||||
default_exclude_patterns = [
|
||||
'*~',
|
||||
]
|
||||
|
||||
sources = []
|
||||
|
||||
data = DoxyfileParse(node.get_contents())
|
||||
|
||||
if data.get("RECURSIVE", "NO") == "YES":
|
||||
recursive = True
|
||||
else:
|
||||
recursive = False
|
||||
|
||||
file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
|
||||
exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
|
||||
|
||||
#
|
||||
# We're running in the top-level directory, but the doxygen
|
||||
# configuration file is in the same directory as node; this means
|
||||
# that relative pathnames in node must be adjusted before they can
|
||||
# go onto the sources list
|
||||
conf_dir = os.path.dirname(str(node))
|
||||
|
||||
for node in data.get("INPUT", []):
|
||||
if not os.path.isabs(node):
|
||||
node = os.path.join(conf_dir, node)
|
||||
if os.path.isfile(node):
|
||||
sources.append(node)
|
||||
elif os.path.isdir(node):
|
||||
if recursive:
|
||||
for root, dirs, files in os.walk(node):
|
||||
for f in files:
|
||||
filename = os.path.join(root, f)
|
||||
|
||||
pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False)
|
||||
exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True)
|
||||
|
||||
if pattern_check and not exclude_check:
|
||||
sources.append(filename)
|
||||
else:
|
||||
for pattern in file_patterns:
|
||||
sources.extend(glob.glob("/".join([node, pattern])))
|
||||
|
||||
sources = map( lambda path: env.File(path), sources )
|
||||
return sources
|
||||
|
||||
|
||||
def DoxySourceScanCheck(node, env):
|
||||
"""Check if we should scan this file"""
|
||||
return os.path.isfile(node.path)
|
||||
|
||||
def DoxyEmitter(source, target, env):
|
||||
"""Doxygen Doxyfile emitter"""
|
||||
# possible output formats and their default values and output locations
|
||||
output_formats = {
|
||||
"HTML": ("YES", "html"),
|
||||
"LATEX": ("YES", "latex"),
|
||||
"RTF": ("NO", "rtf"),
|
||||
"MAN": ("NO", "man"),
|
||||
"XML": ("NO", "xml"),
|
||||
}
|
||||
|
||||
data = DoxyfileParse(source[0].get_contents())
|
||||
|
||||
targets = []
|
||||
out_dir = data.get("OUTPUT_DIRECTORY", ".")
|
||||
|
||||
# add our output locations
|
||||
for (k, v) in output_formats.items():
|
||||
if data.get("GENERATE_" + k, v[0]) == "YES":
|
||||
targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) )
|
||||
|
||||
# don't clobber targets
|
||||
for node in targets:
|
||||
env.Precious(node)
|
||||
|
||||
# set up cleaning stuff
|
||||
for node in targets:
|
||||
env.Clean(node, node)
|
||||
|
||||
return (targets, source)
|
||||
|
||||
|
||||
def generate(env):
|
||||
"""
|
||||
Add builders and construction variables for the
|
||||
Doxygen tool. This is currently for Doxygen 1.4.6.
|
||||
"""
|
||||
doxyfile_scanner = env.Scanner(
|
||||
DoxySourceScan,
|
||||
"DoxySourceScan",
|
||||
scan_check = DoxySourceScanCheck,
|
||||
)
|
||||
|
||||
import SCons.Builder
|
||||
doxyfile_builder = SCons.Builder.Builder(
|
||||
action = "cd ${SOURCE.dir} && (${DOXYGEN} ${SOURCE.file} 2>&1 |tee ,doxylog)",
|
||||
emitter = DoxyEmitter,
|
||||
target_factory = env.fs.Entry,
|
||||
single_source = True,
|
||||
source_scanner = doxyfile_scanner,
|
||||
)
|
||||
|
||||
env.Append(BUILDERS = {
|
||||
'Doxygen': doxyfile_builder,
|
||||
})
|
||||
|
||||
env.AppendUnique(
|
||||
DOXYGEN = 'doxygen',
|
||||
)
|
||||
|
||||
def exists(env):
|
||||
"""
|
||||
Make sure doxygen exists.
|
||||
"""
|
||||
return env.Detect("doxygen")
|
||||
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
# along with this program; if not, see http://www.gnu.org/licenses/
|
||||
#####################################################################
|
||||
|
||||
# history: 8/2008 adapted for Lumiera build system
|
||||
|
|
|
|||
1
doc/devel/.gitignore
vendored
1
doc/devel/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
,doxylog
|
||||
warnings.txt
|
||||
html/*
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = Lumiera
|
||||
PROJECT_NUMBER = 3.0+alpha
|
||||
PROJECT_NUMBER = 0.1+pre
|
||||
OUTPUT_DIRECTORY =
|
||||
CREATE_SUBDIRS = YES
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
|
@ -32,7 +32,7 @@ SHORT_NAMES = NO
|
|||
JAVADOC_AUTOBRIEF = YES
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
DETAILS_AT_TOP = YES
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
|
|
@ -65,8 +65,8 @@ CASE_SENSE_NAMES = YES
|
|||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
|
|
@ -179,7 +179,7 @@ HTML_STYLESHEET =
|
|||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_FEEDNAME = "Lumiera Doxygen docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
CHM_FILE =
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ GtkLumiera& application();
|
|||
*/
|
||||
namespace dialogs {}
|
||||
|
||||
/**
|
||||
* The namespace of data model classes.
|
||||
*/
|
||||
namespace model {}
|
||||
|
||||
/**
|
||||
* The namespace of all video output implementations.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -140,16 +140,15 @@ style "timeline_ruler" = "default_base"
|
|||
gtkmm__CustomObject_TimelineRuler::min_division_width = 100
|
||||
gtkmm__CustomObject_TimelineRuler::mouse_chevron_size = 5
|
||||
gtkmm__CustomObject_TimelineRuler::selection_chevron_size = 5
|
||||
gtkmm__CustomObject_TimelineRuler::playback_arrow_colour = "#2D2D90"
|
||||
gtkmm__CustomObject_TimelineRuler::playback_arrow_alpha = 0.5
|
||||
gtkmm__CustomObject_TimelineRuler::playback_arrow_size = 10
|
||||
gtkmm__CustomObject_TimelineRuler::playback_arrow_stem_size = 3
|
||||
}
|
||||
|
||||
style "timeline_header_base" = "default_base"
|
||||
{
|
||||
# fg[NORMAL] = { 0.77, 0.77, 0.72 }
|
||||
# bg[NORMAL] = { 0.18, 0.19, 0.22 }
|
||||
# bg[ACTIVE] = { 0.20, 0.20, 0.20 }
|
||||
# bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
|
||||
# bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
|
||||
# bg[SELECTED] = { 0.20, 0.20, 0.20 }
|
||||
|
||||
}
|
||||
|
||||
class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#include "../gtk-lumiera.hpp"
|
||||
#include "timeline-panel.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "../../lib/time.h"
|
||||
}
|
||||
|
||||
using namespace Gtk;
|
||||
using namespace sigc;
|
||||
using namespace lumiera::gui::widgets;
|
||||
|
|
@ -39,14 +43,24 @@ TimelinePanel::TimelinePanel() :
|
|||
iBeamTool(Gtk::StockID("tool_i_beam")),
|
||||
zoomIn(Stock::ZOOM_IN),
|
||||
zoomOut(Stock::ZOOM_OUT),
|
||||
timeIndicator(),
|
||||
updatingToolbar(false)
|
||||
{
|
||||
// Setup the widget
|
||||
timelineWidget.mouse_hover_signal().connect(
|
||||
mem_fun(this, &TimelinePanel::on_mouse_hover));
|
||||
|
||||
// Setup the toolbar
|
||||
timeIndicatorButton.set_label_widget(timeIndicator);
|
||||
toolbar.append(timeIndicatorButton);
|
||||
|
||||
toolbar.append(seperator1);
|
||||
|
||||
toolbar.append(arrowTool, mem_fun(this,
|
||||
&TimelinePanel::on_arrow_tool));
|
||||
toolbar.append(iBeamTool, mem_fun(this,
|
||||
&TimelinePanel::on_ibeam_tool));
|
||||
toolbar.append(seperator1);
|
||||
toolbar.append(seperator2);
|
||||
toolbar.append(zoomIn, mem_fun(this, &TimelinePanel::on_zoom_in));
|
||||
toolbar.append(zoomOut, mem_fun(this, &TimelinePanel::on_zoom_out));
|
||||
|
||||
|
|
@ -58,8 +72,10 @@ TimelinePanel::TimelinePanel() :
|
|||
pack_start(toolbar, PACK_SHRINK);
|
||||
pack_start(timelineWidget, PACK_EXPAND_WIDGET);
|
||||
|
||||
// Set the initial UI state
|
||||
update_tool_buttons();
|
||||
update_zoom_buttons();
|
||||
show_time(0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -93,6 +109,12 @@ TimelinePanel::on_zoom_out()
|
|||
update_zoom_buttons();
|
||||
}
|
||||
|
||||
void
|
||||
TimelinePanel::on_mouse_hover(gavl_time_t time)
|
||||
{
|
||||
show_time(time);
|
||||
}
|
||||
|
||||
void
|
||||
TimelinePanel::update_tool_buttons()
|
||||
{
|
||||
|
|
@ -114,6 +136,12 @@ TimelinePanel::update_zoom_buttons()
|
|||
TimelineWidget::MaxScale);
|
||||
}
|
||||
|
||||
void
|
||||
TimelinePanel::show_time(gavl_time_t time)
|
||||
{
|
||||
timeIndicator.set_text(lumiera_tmpbuf_print_time(time));
|
||||
}
|
||||
|
||||
} // namespace panels
|
||||
} // namespace gui
|
||||
} // namespace lumiera
|
||||
|
|
|
|||
|
|
@ -55,9 +55,15 @@ private:
|
|||
void on_zoom_in();
|
||||
void on_zoom_out();
|
||||
|
||||
void on_time_pressed();
|
||||
|
||||
void on_mouse_hover(gavl_time_t time);
|
||||
|
||||
private:
|
||||
void update_tool_buttons();
|
||||
void update_zoom_buttons();
|
||||
|
||||
void show_time(gavl_time_t time);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -65,6 +71,7 @@ private:
|
|||
|
||||
// Widgets
|
||||
Gtk::Toolbar toolbar;
|
||||
Gtk::HBox toolStrip;
|
||||
TimelineWidget timelineWidget;
|
||||
|
||||
// Toolbar Widgets
|
||||
|
|
@ -76,6 +83,11 @@ private:
|
|||
Gtk::ToolButton zoomIn;
|
||||
Gtk::ToolButton zoomOut;
|
||||
|
||||
Gtk::SeparatorToolItem seperator2;
|
||||
|
||||
Gtk::Label timeIndicator;
|
||||
Gtk::ToolButton timeIndicatorButton;
|
||||
|
||||
// Internals
|
||||
bool updatingToolbar;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ TimelineWidget::TimelineWidget() :
|
|||
verticalAdjustment(0, 0, 0),
|
||||
selectionStart(0),
|
||||
selectionEnd(0),
|
||||
playbackPeriodStart(0),
|
||||
playbackPeriodEnd(0),
|
||||
horizontalScroll(horizontalAdjustment),
|
||||
verticalScroll(verticalAdjustment)
|
||||
{
|
||||
|
|
@ -108,7 +110,8 @@ TimelineWidget::set_time_offset(gavl_time_t time_offset)
|
|||
|
||||
timeOffset = time_offset;
|
||||
horizontalAdjustment.set_value(time_offset);
|
||||
ruler->update_view();
|
||||
|
||||
viewChangedSignal.emit();
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
|
@ -127,7 +130,7 @@ TimelineWidget::set_time_scale(int64_t time_scale)
|
|||
const int view_width = body->get_allocation().get_width();
|
||||
horizontalAdjustment.set_page_size(timeScale * view_width);
|
||||
|
||||
ruler->update_view();
|
||||
viewChangedSignal.emit();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -183,8 +186,12 @@ TimelineWidget::get_selection_end() const
|
|||
}
|
||||
|
||||
void
|
||||
TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end)
|
||||
TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end,
|
||||
bool reset_playback_period)
|
||||
{
|
||||
REQUIRE(ruler != NULL);
|
||||
REQUIRE(body != NULL);
|
||||
|
||||
if(start < end)
|
||||
{
|
||||
selectionStart = start;
|
||||
|
|
@ -196,6 +203,46 @@ TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end)
|
|||
selectionStart = end;
|
||||
selectionEnd = start;
|
||||
}
|
||||
|
||||
if(reset_playback_period)
|
||||
{
|
||||
playbackPeriodStart = selectionStart;
|
||||
playbackPeriodEnd = selectionEnd;
|
||||
}
|
||||
|
||||
ruler->queue_draw();
|
||||
body->queue_draw();
|
||||
}
|
||||
|
||||
gavl_time_t
|
||||
TimelineWidget::get_playback_period_start() const
|
||||
{
|
||||
return playbackPeriodStart;
|
||||
}
|
||||
|
||||
gavl_time_t
|
||||
TimelineWidget::get_playback_period_end() const
|
||||
{
|
||||
return playbackPeriodEnd;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineWidget::set_playback_period(gavl_time_t start, gavl_time_t end)
|
||||
{
|
||||
REQUIRE(ruler != NULL);
|
||||
REQUIRE(body != NULL);
|
||||
|
||||
if(start < end)
|
||||
{
|
||||
playbackPeriodStart = start;
|
||||
playbackPeriodEnd = end;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The period is back-to-front, flip it round
|
||||
playbackPeriodStart = end;
|
||||
playbackPeriodEnd = start;
|
||||
}
|
||||
|
||||
ruler->queue_draw();
|
||||
body->queue_draw();
|
||||
|
|
@ -215,11 +262,23 @@ TimelineWidget::set_tool(ToolType tool_type)
|
|||
body->set_tool(tool_type);
|
||||
}
|
||||
|
||||
sigc::signal<void>
|
||||
TimelineWidget::view_changed_signal() const
|
||||
{
|
||||
return viewChangedSignal;
|
||||
}
|
||||
|
||||
sigc::signal<void, gavl_time_t>
|
||||
TimelineWidget::mouse_hover_signal() const
|
||||
{
|
||||
return mouseHoverSignal;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineWidget::on_scroll()
|
||||
{
|
||||
timeOffset = horizontalAdjustment.get_value();
|
||||
ruler->update_view();
|
||||
viewChangedSignal.emit();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -309,6 +368,7 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event)
|
|||
{
|
||||
REQUIRE(event != NULL);
|
||||
ruler->set_mouse_chevron_offset(event->x);
|
||||
mouseHoverSignal.emit(x_to_time(event->x));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,8 +120,30 @@ public:
|
|||
|
||||
/**
|
||||
* Sets the period of the selection.
|
||||
* @param start The start time.
|
||||
* @param end The end time.
|
||||
* @param reset_playback_period Specifies whether to set the playback
|
||||
* period to the same as this new selection.
|
||||
*/
|
||||
void set_selection(gavl_time_t start, gavl_time_t end);
|
||||
void set_selection(gavl_time_t start, gavl_time_t end,
|
||||
bool reset_playback_period = true);
|
||||
|
||||
/**
|
||||
* Gets the time at which the playback period begins.
|
||||
*/
|
||||
gavl_time_t get_playback_period_start() const;
|
||||
|
||||
/**
|
||||
* Gets the time at which the playback period ends.
|
||||
*/
|
||||
gavl_time_t get_playback_period_end() const;
|
||||
|
||||
/**
|
||||
* Sets the playback period.
|
||||
* @param start The start time.
|
||||
* @param end The end time.
|
||||
*/
|
||||
void set_playback_period(gavl_time_t start, gavl_time_t end);
|
||||
|
||||
/**
|
||||
* Gets the type of the tool currently active.
|
||||
|
|
@ -132,6 +154,12 @@ public:
|
|||
* Sets the type of the tool currently active.
|
||||
*/
|
||||
void set_tool(timeline::ToolType tool_type);
|
||||
|
||||
public:
|
||||
/* ===== Signals ===== */
|
||||
sigc::signal<void> view_changed_signal() const;
|
||||
|
||||
sigc::signal<void, gavl_time_t> mouse_hover_signal() const;
|
||||
|
||||
/* ===== Events ===== */
|
||||
protected:
|
||||
|
|
@ -165,6 +193,8 @@ protected:
|
|||
// Selection State
|
||||
gavl_time_t selectionStart;
|
||||
gavl_time_t selectionEnd;
|
||||
gavl_time_t playbackPeriodStart;
|
||||
gavl_time_t playbackPeriodEnd;
|
||||
|
||||
int totalHeight;
|
||||
|
||||
|
|
@ -179,9 +209,18 @@ protected:
|
|||
Gtk::Adjustment horizontalAdjustment, verticalAdjustment;
|
||||
Gtk::HScrollbar horizontalScroll;
|
||||
Gtk::VScrollbar verticalScroll;
|
||||
|
||||
// Signals
|
||||
sigc::signal<void> viewChangedSignal;
|
||||
sigc::signal<void, gavl_time_t> mouseHoverSignal;
|
||||
|
||||
/* ===== Constants ===== */
|
||||
public:
|
||||
/**
|
||||
* The maximum scale for timeline display.
|
||||
* @remarks At MaxScale, every pixel on the timeline is equivalent
|
||||
* to 30000000 gavl_time_t increments.
|
||||
*/
|
||||
static const int64_t MaxScale;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -55,10 +55,8 @@ TimelineBody::TimelineBody(lumiera::gui::widgets::TimelineWidget
|
|||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
// Connect up some events
|
||||
timelineWidget->horizontalAdjustment.signal_value_changed().connect(
|
||||
sigc::mem_fun(this, &TimelineBody::on_scroll) );
|
||||
timelineWidget->verticalAdjustment.signal_value_changed().connect(
|
||||
sigc::mem_fun(this, &TimelineBody::on_scroll) );
|
||||
timelineWidget->view_changed_signal().connect(sigc::mem_fun(
|
||||
this, &TimelineBody::on_update_view) );
|
||||
|
||||
// Install style properties
|
||||
register_styles();
|
||||
|
|
@ -109,6 +107,12 @@ TimelineBody::set_tool(timeline::ToolType tool_type)
|
|||
tool->apply_cursor();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::on_update_view()
|
||||
{
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::on_realize()
|
||||
{
|
||||
|
|
@ -125,112 +129,6 @@ TimelineBody::on_realize()
|
|||
tool->apply_cursor();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::on_scroll()
|
||||
{
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_scroll_event (GdkEventScroll* event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
if(event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Zoom in
|
||||
timelineWidget->zoom_view(event->x, 16);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Zoom out
|
||||
timelineWidget->zoom_view(event->x, -16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Shift 1/16th left
|
||||
timelineWidget->shift_view(-16);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Shift 1/16th right
|
||||
timelineWidget->shift_view(16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_button_press_event(GdkEventButton* event)
|
||||
{
|
||||
mouseDownX = event->x;
|
||||
mouseDownY = event->y;
|
||||
|
||||
switch(event->button)
|
||||
{
|
||||
case 2:
|
||||
begin_shift_drag();
|
||||
break;
|
||||
|
||||
default:
|
||||
dragType = None;
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_button_press_event(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_button_release_event(GdkEventButton* event)
|
||||
{
|
||||
// Terminate any drags
|
||||
dragType = None;
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_button_release_event(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
switch(dragType)
|
||||
{
|
||||
case Shift:
|
||||
{
|
||||
const int64_t scale = timelineWidget->get_time_scale();
|
||||
gavl_time_t offset = beginShiftTimeOffset +
|
||||
(int64_t)(mouseDownX - event->x) * scale;
|
||||
timelineWidget->set_time_offset(offset);
|
||||
|
||||
set_vertical_offset((int)(mouseDownY - event->y) +
|
||||
beginShiftVerticalOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_motion_notify_event(event);
|
||||
|
||||
// false so that the message is passed up to the owner TimelineWidget
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_expose_event(GdkEventExpose* event)
|
||||
{
|
||||
|
|
@ -323,6 +221,106 @@ TimelineBody::on_expose_event(GdkEventExpose* event)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_scroll_event (GdkEventScroll* event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
if(event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Zoom in
|
||||
timelineWidget->zoom_view(event->x, 1);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Zoom out
|
||||
timelineWidget->zoom_view(event->x, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Shift 1/16th left
|
||||
timelineWidget->shift_view(-16);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Shift 1/16th right
|
||||
timelineWidget->shift_view(16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_button_press_event(GdkEventButton* event)
|
||||
{
|
||||
mouseDownX = event->x;
|
||||
mouseDownY = event->y;
|
||||
|
||||
switch(event->button)
|
||||
{
|
||||
case 2:
|
||||
begin_shift_drag();
|
||||
break;
|
||||
|
||||
default:
|
||||
dragType = None;
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_button_press_event(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_button_release_event(GdkEventButton* event)
|
||||
{
|
||||
// Terminate any drags
|
||||
dragType = None;
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_button_release_event(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
switch(dragType)
|
||||
{
|
||||
case Shift:
|
||||
{
|
||||
const int64_t scale = timelineWidget->get_time_scale();
|
||||
gavl_time_t offset = beginShiftTimeOffset +
|
||||
(int64_t)(mouseDownX - event->x) * scale;
|
||||
timelineWidget->set_time_offset(offset);
|
||||
|
||||
set_vertical_offset((int)(mouseDownY - event->y) +
|
||||
beginShiftVerticalOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_motion_notify_event(event);
|
||||
|
||||
// false so that the message is passed up to the owner TimelineWidget
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::begin_shift_drag()
|
||||
|
|
@ -349,23 +347,18 @@ TimelineBody::register_styles() const
|
|||
{
|
||||
GtkWidgetClass *klass = GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj()));
|
||||
|
||||
gtk_widget_class_install_style_property(
|
||||
GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())),
|
||||
g_param_spec_boxed("background",
|
||||
"Track Background",
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_boxed("background", "Track Background",
|
||||
"The background colour of timeline tracks",
|
||||
GDK_TYPE_COLOR, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(
|
||||
GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())),
|
||||
g_param_spec_boxed("selection",
|
||||
"End lines of a selection",
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_boxed("selection", "End lines of a selection",
|
||||
"The colour of selection limit lines",
|
||||
GDK_TYPE_COLOR, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_float("selection_alpha",
|
||||
"Selection Alpha",
|
||||
g_param_spec_float("selection_alpha", "Selection Alpha",
|
||||
"The transparency of the selection marque.",
|
||||
0, 1.0, 0.5, G_PARAM_READABLE));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,33 +37,72 @@ class TimelineWidget;
|
|||
|
||||
namespace timeline {
|
||||
|
||||
/**
|
||||
* Implementation of the timeline body subwidget. This widget is
|
||||
* displayed in the centre of the timeline widget, and displays the
|
||||
* content of all timeline tracks.
|
||||
*/
|
||||
class TimelineBody : public Gtk::DrawingArea
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param timeline_widget The owner widget of this ruler.
|
||||
*/
|
||||
TimelineBody(lumiera::gui::widgets::TimelineWidget *timeline_widget);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~TimelineBody();
|
||||
|
||||
/**
|
||||
* Returns the type of the currently selected timeline tool.
|
||||
*/
|
||||
ToolType get_tool() const;
|
||||
|
||||
/**
|
||||
* Selects a tool of a specified type.
|
||||
* @param tool_type The type of tool to set.
|
||||
*/
|
||||
void set_tool(ToolType tool_type);
|
||||
|
||||
/* ===== Events ===== */
|
||||
protected:
|
||||
void on_realize();
|
||||
|
||||
void on_scroll();
|
||||
/**
|
||||
* An event handler for when the view window of the timeline changes.
|
||||
*/
|
||||
void on_update_view();
|
||||
|
||||
/**
|
||||
* An event handler for when the widget is realized.
|
||||
*/
|
||||
void on_realize();
|
||||
|
||||
/**
|
||||
* An event handler for when the window must be redrawn.
|
||||
*/
|
||||
bool on_expose_event(GdkEventExpose* event);
|
||||
|
||||
bool on_scroll_event(GdkEventScroll* event);
|
||||
|
||||
bool on_button_press_event (GdkEventButton* event);
|
||||
/**
|
||||
* The event handler for button press events.
|
||||
*/
|
||||
bool on_button_press_event(GdkEventButton* event);
|
||||
|
||||
bool on_button_release_event (GdkEventButton* event);
|
||||
/**
|
||||
* The event handler for button release events.
|
||||
*/
|
||||
bool on_button_release_event(GdkEventButton* event);
|
||||
|
||||
/**
|
||||
* The event handler for mouse move events.
|
||||
*/
|
||||
bool on_motion_notify_event(GdkEventMotion *event);
|
||||
|
||||
bool on_expose_event(GdkEventExpose* event);
|
||||
|
||||
/* ===== Internals ===== */
|
||||
private:
|
||||
void begin_shift_drag();
|
||||
|
|
@ -72,8 +111,14 @@ private:
|
|||
|
||||
void set_vertical_offset(int offset);
|
||||
|
||||
/**
|
||||
* Registers all the styles that this class will respond to.
|
||||
*/
|
||||
void register_styles() const;
|
||||
|
||||
/**
|
||||
* Reads styles from the present stylesheet.
|
||||
*/
|
||||
void read_styles();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ IBeamTool::on_button_press_event(GdkEventButton* event)
|
|||
Tool::on_button_press_event(event);
|
||||
|
||||
TimelineWidget *timeline_widget = get_timeline_widget();
|
||||
REQUIRE(timeline_widget != NULL);
|
||||
|
||||
if(event->button == 1)
|
||||
{
|
||||
|
|
@ -181,12 +182,16 @@ void
|
|||
IBeamTool::set_leading_x(const int x)
|
||||
{
|
||||
TimelineWidget *timeline_widget = get_timeline_widget();
|
||||
REQUIRE(timeline_widget != NULL);
|
||||
|
||||
const bool set_playback_period = dragType == Selection;
|
||||
const gavl_time_t time = timeline_widget->x_to_time(x);
|
||||
if(time > pinnedDragTime)
|
||||
timeline_widget->set_selection(pinnedDragTime, time);
|
||||
timeline_widget->set_selection(
|
||||
pinnedDragTime, time, set_playback_period);
|
||||
else
|
||||
timeline_widget->set_selection(time, pinnedDragTime);
|
||||
timeline_widget->set_selection(
|
||||
time, pinnedDragTime, set_playback_period);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ namespace timeline {
|
|||
TimelineRuler::TimelineRuler(
|
||||
lumiera::gui::widgets::TimelineWidget *timeline_widget) :
|
||||
Glib::ObjectBase("TimelineRuler"),
|
||||
isDragging(false),
|
||||
pinnedDragTime(0),
|
||||
mouseChevronOffset(0),
|
||||
annotationHorzMargin(0),
|
||||
annotationVertMargin(0),
|
||||
|
|
@ -54,10 +56,17 @@ TimelineRuler::TimelineRuler(
|
|||
minDivisionWidth(100),
|
||||
mouseChevronSize(5),
|
||||
selectionChevronSize(5),
|
||||
playbackArrowAlpha(0.5f),
|
||||
playbackArrowSize(10),
|
||||
playbackArrowStemSize(3),
|
||||
timelineWidget(timeline_widget)
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
// Connect event handlers
|
||||
timelineWidget->view_changed_signal().connect(sigc::mem_fun(
|
||||
this, &TimelineRuler::on_update_view) );
|
||||
|
||||
// Install style properties
|
||||
register_styles();
|
||||
}
|
||||
|
|
@ -70,7 +79,7 @@ TimelineRuler::set_mouse_chevron_offset(int offset)
|
|||
}
|
||||
|
||||
void
|
||||
TimelineRuler::update_view()
|
||||
TimelineRuler::on_update_view()
|
||||
{
|
||||
rulerImage.clear();
|
||||
queue_draw();
|
||||
|
|
@ -82,7 +91,10 @@ TimelineRuler::on_realize()
|
|||
Widget::on_realize();
|
||||
|
||||
// Set event notifications
|
||||
add_events(Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK);
|
||||
add_events(Gdk::POINTER_MOTION_MASK |
|
||||
Gdk::SCROLL_MASK |
|
||||
Gdk::BUTTON_PRESS_MASK |
|
||||
Gdk::BUTTON_RELEASE_MASK);
|
||||
|
||||
// Load styles
|
||||
read_styles();
|
||||
|
|
@ -130,16 +142,47 @@ TimelineRuler::on_expose_event(GdkEventExpose* event)
|
|||
// Draw the overlays
|
||||
draw_mouse_chevron(cr, allocation);
|
||||
draw_selection(cr, allocation);
|
||||
draw_playback_period(cr, allocation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TimelineRuler::on_button_press_event(GdkEventButton* event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
if(event->button == 1)
|
||||
{
|
||||
pinnedDragTime = timelineWidget->x_to_time(event->x);
|
||||
isDragging = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineRuler::on_button_release_event(GdkEventButton* event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
if(event->button == 1)
|
||||
isDragging = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TimelineRuler::on_motion_notify_event(GdkEventMotion *event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
set_mouse_chevron_offset(event->x);
|
||||
|
||||
if(isDragging)
|
||||
set_leading_x(event->x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +205,18 @@ TimelineRuler::on_size_allocate(Gtk::Allocation& allocation)
|
|||
rulerImage.clear(); // The widget has changed size - redraw
|
||||
}
|
||||
|
||||
void
|
||||
TimelineRuler::set_leading_x(const int x)
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
const gavl_time_t time = timelineWidget->x_to_time(x);
|
||||
if(time > pinnedDragTime)
|
||||
timelineWidget->set_playback_period(pinnedDragTime, time);
|
||||
else
|
||||
timelineWidget->set_playback_period(time, pinnedDragTime);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineRuler::draw_ruler(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect)
|
||||
|
|
@ -171,8 +226,8 @@ TimelineRuler::draw_ruler(Cairo::RefPtr<Cairo::Context> cr,
|
|||
REQUIRE(ruler_rect.get_height() > 0);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
const gavl_time_t left_offset = timelineWidget->timeOffset;
|
||||
const int64_t time_scale = timelineWidget->timeScale;
|
||||
const gavl_time_t left_offset = timelineWidget->get_time_offset();
|
||||
const int64_t time_scale = timelineWidget->get_time_scale();
|
||||
|
||||
// Preparation steps
|
||||
const int height = ruler_rect.get_height();
|
||||
|
|
@ -299,6 +354,74 @@ TimelineRuler::draw_selection(Cairo::RefPtr<Cairo::Context> cr,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineRuler::draw_playback_period(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect)
|
||||
{
|
||||
REQUIRE(cr);
|
||||
REQUIRE(ruler_rect.get_width() > 0);
|
||||
REQUIRE(ruler_rect.get_height() > 0);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
// Calculate coordinates
|
||||
const float halfSize = playbackArrowSize / 2;
|
||||
|
||||
const float a = timelineWidget->time_to_x(
|
||||
timelineWidget->playbackPeriodStart) + 1 + 0.5f;
|
||||
const float b = a + halfSize;
|
||||
const float d = timelineWidget->time_to_x(
|
||||
timelineWidget->playbackPeriodEnd) + 0.5f;
|
||||
const float c = d - halfSize;
|
||||
|
||||
const float e = ruler_rect.get_height() - playbackArrowSize - 0.5f;
|
||||
const float f = e + (playbackArrowSize - playbackArrowStemSize) / 2;
|
||||
const float g = ruler_rect.get_height() - playbackArrowSize / 2
|
||||
- 0.5f;
|
||||
const float i = ruler_rect.get_height() - 0.5f;
|
||||
const float h = i - (playbackArrowSize - playbackArrowStemSize) / 2;
|
||||
|
||||
// Contruct the path
|
||||
if(d - a >= playbackArrowSize)
|
||||
{
|
||||
// Draw an arrow: <===>
|
||||
cr->move_to(a, g);
|
||||
cr->line_to(b, e);
|
||||
cr->line_to(b, f);
|
||||
cr->line_to(c, f);
|
||||
cr->line_to(c, e);
|
||||
cr->line_to(d, g);
|
||||
cr->line_to(c, i);
|
||||
cr->line_to(c, h);
|
||||
cr->line_to(b, h);
|
||||
cr->line_to(b, i);
|
||||
cr->line_to(a, g);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The space is too narrow for an arrow, so draw calipers: > <
|
||||
cr->move_to(a, g);
|
||||
cr->rel_line_to(-halfSize, -halfSize);
|
||||
cr->rel_line_to(0, playbackArrowSize);
|
||||
|
||||
cr->move_to(d, g);
|
||||
cr->rel_line_to(halfSize, -halfSize);
|
||||
cr->rel_line_to(0, playbackArrowSize);
|
||||
}
|
||||
|
||||
// Fill
|
||||
cr->set_source_rgba(
|
||||
(float)playbackArrowColour.red / 0xFFFF,
|
||||
(float)playbackArrowColour.green / 0xFFFF,
|
||||
(float)playbackArrowColour.blue / 0xFFFF,
|
||||
playbackArrowAlpha);
|
||||
cr->fill_preserve();
|
||||
|
||||
// Stroke
|
||||
gdk_cairo_set_source_color(cr->cobj(), &playbackArrowColour);
|
||||
cr->set_line_width(1);
|
||||
cr->stroke();
|
||||
}
|
||||
|
||||
gavl_time_t
|
||||
TimelineRuler::calculate_major_spacing() const
|
||||
{
|
||||
|
|
@ -402,6 +525,29 @@ TimelineRuler::register_styles() const
|
|||
"Selection Chevron Size",
|
||||
"The height of the selection chevrons in pixels.",
|
||||
0, G_MAXINT, 5, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_boxed("playback_arrow_colour",
|
||||
"End lines of a selection",
|
||||
"The colour of selection limit lines",
|
||||
GDK_TYPE_COLOR, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_float("playback_arrow_alpha", "Playback Arrow Alpha",
|
||||
"The transparency of the playback period arrow.",
|
||||
0, 1.0, 0.5, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_int("playback_arrow_size",
|
||||
"Playback Arrow Head Size",
|
||||
"The height of the playback arrow head in pixels.",
|
||||
0, G_MAXINT, 10, G_PARAM_READABLE));
|
||||
|
||||
gtk_widget_class_install_style_property(klass,
|
||||
g_param_spec_int("playback_arrow_stem_size",
|
||||
"Playback Arrow Stem Size",
|
||||
"The height of the playback arrow head in pixels.",
|
||||
0, G_MAXINT, 3, G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -415,6 +561,13 @@ TimelineRuler::read_styles()
|
|||
get_style_property("min_division_width", minDivisionWidth);
|
||||
get_style_property("mouse_chevron_size", mouseChevronSize);
|
||||
get_style_property("selection_chevron_size", selectionChevronSize);
|
||||
|
||||
playbackArrowColour = WindowManager::read_style_colour_property(
|
||||
*this, "playback_arrow_colour", 0, 0, 0);
|
||||
get_style_property("playback_arrow_alpha", playbackArrowAlpha);
|
||||
get_style_property("playback_arrow_size", playbackArrowSize);
|
||||
get_style_property("playback_arrow_stem_size",
|
||||
playbackArrowStemSize);
|
||||
}
|
||||
|
||||
} // namespace timeline
|
||||
|
|
|
|||
|
|
@ -37,54 +37,154 @@ class TimelineWidget;
|
|||
|
||||
namespace timeline {
|
||||
|
||||
/**
|
||||
* A subwidget of the TimelineWidget. This class implements a ruler
|
||||
* which is placed along the top edge of the timeline.
|
||||
*/
|
||||
class TimelineRuler : public Gtk::DrawingArea
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param timeline_widget The owner widget of this ruler.
|
||||
*/
|
||||
TimelineRuler(
|
||||
lumiera::gui::widgets::TimelineWidget *timeline_widget);
|
||||
|
||||
/**
|
||||
* Sets the offset of the mouse chevron in pixels from the left
|
||||
* edge of the widget. If offset is less than 0 or greater than the
|
||||
* width, the chevron will not be visible.
|
||||
* Sets offset of the mouse chevron
|
||||
* @param offset The offset of the mouse chevron in pixels from the
|
||||
* left edge of the widget. If offset is less than 0 or greater than
|
||||
* the width, the chevron will not be visible.
|
||||
*/
|
||||
void set_mouse_chevron_offset(int offset);
|
||||
|
||||
void update_view();
|
||||
|
||||
/* ===== Events ===== */
|
||||
protected:
|
||||
private:
|
||||
/**
|
||||
* An event handler for when the view window of the timeline changes.
|
||||
* @remarks Causes the ruler to be redrawn from scratch. The cached
|
||||
* ruler backdrop is destroyed and redrawn.
|
||||
*/
|
||||
void on_update_view();
|
||||
|
||||
/**
|
||||
* An event handler for when the widget is realized.
|
||||
*/
|
||||
void on_realize();
|
||||
|
||||
/**
|
||||
* An event handler for when the window must be redrawn.
|
||||
*/
|
||||
bool on_expose_event(GdkEventExpose *event);
|
||||
|
||||
/**
|
||||
* The event handler for button press events.
|
||||
*/
|
||||
bool on_button_press_event(GdkEventButton* event);
|
||||
|
||||
/**
|
||||
* The event handler for button release events.
|
||||
*/
|
||||
bool on_button_release_event(GdkEventButton* event);
|
||||
|
||||
/**
|
||||
* The event handler for mouse move events.
|
||||
*/
|
||||
bool on_motion_notify_event(GdkEventMotion *event);
|
||||
|
||||
/**
|
||||
* The handler for when the widget must calculate it's new shape.
|
||||
*/
|
||||
void on_size_request(Gtk::Requisition *requisition);
|
||||
|
||||
/**
|
||||
* The handler for when the widget must take the size of a given
|
||||
* area.
|
||||
*/
|
||||
void on_size_allocate(Gtk::Allocation& allocation);
|
||||
|
||||
/* ===== Internals ===== */
|
||||
private:
|
||||
void draw_ruler(Cairo::RefPtr<Cairo::Context> cairo,
|
||||
/* ===== Internal Methods ===== */
|
||||
|
||||
/**
|
||||
* As the user drags, this function is called to update the position
|
||||
* of the moving end of the playback period.
|
||||
*/
|
||||
void set_leading_x(const int x);
|
||||
|
||||
/**
|
||||
* Draws the ruler graduations.
|
||||
* @param cr The cairo context to draw the ruler into.
|
||||
* @param ruler_rect The area of the ruler widget.
|
||||
*/
|
||||
void draw_ruler(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect);
|
||||
|
||||
/**
|
||||
* Overlays the mouse chevron.
|
||||
* @param cr The cairo context to draw the chevron into.
|
||||
* @param ruler_rect The area of the ruler widget.
|
||||
*/
|
||||
void draw_mouse_chevron(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect);
|
||||
|
||||
/**
|
||||
* Overlays the currently selected period.
|
||||
* @param cr The cairo context to draw the selection into.
|
||||
* @param ruler_rect The area of the ruler widget.
|
||||
*/
|
||||
void draw_selection(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect);
|
||||
|
||||
gavl_time_t calculate_major_spacing() const;
|
||||
|
||||
/**
|
||||
* Overlays the currently selected playback period.
|
||||
* @param cr The cairo context to draw the period into.
|
||||
* @param ruler_rect The area of the ruler widget.
|
||||
*/
|
||||
void draw_playback_period(Cairo::RefPtr<Cairo::Context> cr,
|
||||
const Gdk::Rectangle ruler_rect);
|
||||
|
||||
/**
|
||||
* Given the current zoom, this function calculates the preiod
|
||||
* between major graduations on the ruler scale.
|
||||
* @return The period as a gavl_time_t
|
||||
*/
|
||||
gavl_time_t calculate_major_spacing() const;
|
||||
|
||||
/**
|
||||
* Registers all the styles that this class will respond to.
|
||||
*/
|
||||
void register_styles() const;
|
||||
|
||||
/**
|
||||
* Reads styles from the present stylesheet.
|
||||
*/
|
||||
void read_styles();
|
||||
|
||||
private:
|
||||
|
||||
// State values
|
||||
|
||||
/**
|
||||
* This value is set to true if the user is dragging with the left
|
||||
* mouse button.
|
||||
*/
|
||||
bool isDragging;
|
||||
|
||||
/**
|
||||
* During a selection drag, one end of the selection is moving with
|
||||
* the mouse, the other is pinned. pinnedDragTime specifies the time
|
||||
* of that point.
|
||||
*/
|
||||
gavl_time_t pinnedDragTime;
|
||||
|
||||
// Indicated values
|
||||
/**
|
||||
* The offset from the left of the control in pixels to draw the
|
||||
* mouse chevron. If offset is less than 0 or greater than
|
||||
* the width, the chevron will not be visible.
|
||||
*/
|
||||
int mouseChevronOffset;
|
||||
|
||||
// Style values
|
||||
|
|
@ -96,11 +196,23 @@ private:
|
|||
int minDivisionWidth;
|
||||
int mouseChevronSize;
|
||||
int selectionChevronSize;
|
||||
|
||||
// Owner
|
||||
GdkColor playbackArrowColour;
|
||||
float playbackArrowAlpha;
|
||||
int playbackArrowSize;
|
||||
int playbackArrowStemSize;
|
||||
|
||||
/**
|
||||
* The owner widget
|
||||
*/
|
||||
lumiera::gui::widgets::TimelineWidget *timelineWidget;
|
||||
|
||||
// Cached ruler image
|
||||
/**
|
||||
* The caches image of the ruler, over which the chevrons etc. will
|
||||
* be drawn.
|
||||
* @remarks This backdrop is cached because it changes relatively
|
||||
* infrequently in comparison to the chevrons, thus improving
|
||||
* performance somewhat.
|
||||
*/
|
||||
Cairo::RefPtr<Cairo::ImageSurface> rulerImage;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -95,14 +95,17 @@ Actions::Actions(WorkspaceWindow &workspace_window) :
|
|||
void
|
||||
Actions::update_action_state()
|
||||
{
|
||||
REQUIRE(workspaceWindow.assets_panel != NULL);
|
||||
REQUIRE(workspaceWindow.timeline_panel != NULL);
|
||||
REQUIRE(workspaceWindow.viewer_panel != NULL);
|
||||
REQUIRE(workspaceWindow.assetsPanel != NULL);
|
||||
REQUIRE(workspaceWindow.timelinePanel != NULL);
|
||||
REQUIRE(workspaceWindow.viewerPanel != NULL);
|
||||
|
||||
is_updating_action_state = true;
|
||||
assetsPanelAction->set_active(workspaceWindow.assets_panel->is_shown());
|
||||
timelinePanelAction->set_active(workspaceWindow.timeline_panel->is_shown());
|
||||
viewerPanelAction->set_active(workspaceWindow.viewer_panel->is_shown());
|
||||
assetsPanelAction->set_active(
|
||||
workspaceWindow.assetsPanel->is_shown());
|
||||
timelinePanelAction->set_active(
|
||||
workspaceWindow.timelinePanel->is_shown());
|
||||
viewerPanelAction->set_active(
|
||||
workspaceWindow.viewerPanel->is_shown());
|
||||
is_updating_action_state = false;
|
||||
}
|
||||
|
||||
|
|
@ -148,21 +151,21 @@ void
|
|||
Actions::on_menu_view_assets()
|
||||
{
|
||||
if(!is_updating_action_state)
|
||||
workspaceWindow.assets_panel->show(assetsPanelAction->get_active());
|
||||
workspaceWindow.assetsPanel->show(assetsPanelAction->get_active());
|
||||
}
|
||||
|
||||
void
|
||||
Actions::on_menu_view_timeline()
|
||||
{
|
||||
if(!is_updating_action_state)
|
||||
workspaceWindow.timeline_panel->show(timelinePanelAction->get_active());
|
||||
workspaceWindow.timelinePanel->show(timelinePanelAction->get_active());
|
||||
}
|
||||
|
||||
void
|
||||
Actions::on_menu_view_viewer()
|
||||
{
|
||||
if(!is_updating_action_state)
|
||||
workspaceWindow.viewer_panel->show(viewerPanelAction->get_active());
|
||||
workspaceWindow.viewerPanel->show(viewerPanelAction->get_active());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ WorkspaceWindow::WorkspaceWindow(Project *source_project) :
|
|||
REQUIRE(source_project != NULL);
|
||||
|
||||
layout = NULL;
|
||||
assets_panel = NULL;
|
||||
viewer_panel = NULL;
|
||||
timeline_panel = NULL;
|
||||
assetsPanel = NULL;
|
||||
viewerPanel = NULL;
|
||||
timelinePanel = NULL;
|
||||
|
||||
create_ui();
|
||||
}
|
||||
|
|
@ -61,12 +61,12 @@ WorkspaceWindow::~WorkspaceWindow()
|
|||
REQUIRE(layout != NULL);
|
||||
g_object_unref(layout);
|
||||
|
||||
REQUIRE(assets_panel != NULL);
|
||||
assets_panel->unreference();
|
||||
REQUIRE(viewer_panel != NULL);
|
||||
viewer_panel->unreference();
|
||||
REQUIRE(timeline_panel != NULL);
|
||||
timeline_panel->unreference();
|
||||
REQUIRE(assetsPanel != NULL);
|
||||
assetsPanel->unreference();
|
||||
REQUIRE(viewerPanel != NULL);
|
||||
viewerPanel->unreference();
|
||||
REQUIRE(timelinePanel != NULL);
|
||||
timelinePanel->unreference();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -78,7 +78,7 @@ WorkspaceWindow::create_ui()
|
|||
|
||||
//----- Set up the UI Manager -----//
|
||||
// The UI will be nested within a VBox
|
||||
add(base_container);
|
||||
add(baseContainer);
|
||||
|
||||
uiManager = Gtk::UIManager::create();
|
||||
uiManager->insert_action_group(actions.actionGroup);
|
||||
|
|
@ -131,21 +131,22 @@ WorkspaceWindow::create_ui()
|
|||
//----- Set up the Menu Bar -----//
|
||||
Gtk::Widget* menu_bar = uiManager->get_widget("/MenuBar");
|
||||
ASSERT(menu_bar != NULL);
|
||||
base_container.pack_start(*menu_bar, Gtk::PACK_SHRINK);
|
||||
baseContainer.pack_start(*menu_bar, Gtk::PACK_SHRINK);
|
||||
|
||||
//----- Set up the Tool Bar -----//
|
||||
Gtk::Toolbar* toolbar = dynamic_cast<Gtk::Toolbar*>(uiManager->get_widget("/ToolBar"));
|
||||
Gtk::Toolbar* toolbar = dynamic_cast<Gtk::Toolbar*>(
|
||||
uiManager->get_widget("/ToolBar"));
|
||||
ASSERT(toolbar != NULL);
|
||||
toolbar->set_toolbar_style(TOOLBAR_ICONS);
|
||||
base_container.pack_start(*toolbar, Gtk::PACK_SHRINK);
|
||||
baseContainer.pack_start(*toolbar, Gtk::PACK_SHRINK);
|
||||
|
||||
//----- Create the Panels -----//
|
||||
assets_panel = new AssetsPanel();
|
||||
ENSURE(assets_panel != NULL);
|
||||
viewer_panel = new ViewerPanel();
|
||||
ENSURE(viewer_panel != NULL);
|
||||
timeline_panel = new TimelinePanel();
|
||||
ENSURE(timeline_panel != NULL);
|
||||
assetsPanel = new AssetsPanel();
|
||||
ENSURE(assetsPanel != NULL);
|
||||
viewerPanel = new ViewerPanel();
|
||||
ENSURE(viewerPanel != NULL);
|
||||
timelinePanel = new TimelinePanel();
|
||||
ENSURE(timelinePanel != NULL);
|
||||
|
||||
//----- Create the Dock -----//
|
||||
dock = Glib::wrap(gdl_dock_new());
|
||||
|
|
@ -154,30 +155,41 @@ WorkspaceWindow::create_ui()
|
|||
|
||||
dockbar = Glib::wrap(gdl_dock_bar_new ((GdlDock*)dock->gobj()));
|
||||
|
||||
dock_container.pack_start(*dockbar, PACK_SHRINK);
|
||||
dock_container.pack_end(*dock, PACK_EXPAND_WIDGET);
|
||||
base_container.pack_start(dock_container, PACK_EXPAND_WIDGET);
|
||||
dockContainer.pack_start(*dockbar, PACK_SHRINK);
|
||||
dockContainer.pack_end(*dock, PACK_EXPAND_WIDGET);
|
||||
baseContainer.pack_start(dockContainer, PACK_EXPAND_WIDGET);
|
||||
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(), assets_panel->get_dock_item(), GDL_DOCK_LEFT);
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(), viewer_panel->get_dock_item(), GDL_DOCK_RIGHT);
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(), timeline_panel->get_dock_item(), GDL_DOCK_BOTTOM);
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(),
|
||||
assetsPanel->get_dock_item(), GDL_DOCK_LEFT);
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(),
|
||||
viewerPanel->get_dock_item(), GDL_DOCK_RIGHT);
|
||||
gdl_dock_add_item ((GdlDock*)dock->gobj(),
|
||||
timelinePanel->get_dock_item(), GDL_DOCK_BOTTOM);
|
||||
|
||||
// Manually dock and move around some of the items
|
||||
gdl_dock_item_dock_to (timeline_panel->get_dock_item(),
|
||||
assets_panel->get_dock_item(), GDL_DOCK_BOTTOM, -1);
|
||||
gdl_dock_item_dock_to (viewer_panel->get_dock_item(),
|
||||
assets_panel->get_dock_item(), GDL_DOCK_RIGHT, -1);
|
||||
|
||||
show_all_children();
|
||||
|
||||
gdl_dock_item_dock_to (timelinePanel->get_dock_item(),
|
||||
assetsPanel->get_dock_item(), GDL_DOCK_BOTTOM, -1);
|
||||
gdl_dock_item_dock_to (viewerPanel->get_dock_item(),
|
||||
assetsPanel->get_dock_item(), GDL_DOCK_RIGHT, -1);
|
||||
|
||||
gchar ph1[] = "ph1";
|
||||
gdl_dock_placeholder_new (ph1, (GdlDockObject*)dock->gobj(), GDL_DOCK_TOP, FALSE);
|
||||
gdl_dock_placeholder_new (ph1, (GdlDockObject*)dock->gobj(),
|
||||
GDL_DOCK_TOP, FALSE);
|
||||
gchar ph2[] = "ph2";
|
||||
gdl_dock_placeholder_new (ph2, (GdlDockObject*)dock->gobj(), GDL_DOCK_BOTTOM, FALSE);
|
||||
gdl_dock_placeholder_new (ph2, (GdlDockObject*)dock->gobj(),
|
||||
GDL_DOCK_BOTTOM, FALSE);
|
||||
gchar ph3[] = "ph3";
|
||||
gdl_dock_placeholder_new (ph3, (GdlDockObject*)dock->gobj(), GDL_DOCK_LEFT, FALSE);
|
||||
gdl_dock_placeholder_new (ph3, (GdlDockObject*)dock->gobj(),
|
||||
GDL_DOCK_LEFT, FALSE);
|
||||
gchar ph4[] = "ph4";
|
||||
gdl_dock_placeholder_new (ph4, (GdlDockObject*)dock->gobj(), GDL_DOCK_RIGHT, FALSE);
|
||||
gdl_dock_placeholder_new (ph4, (GdlDockObject*)dock->gobj(),
|
||||
GDL_DOCK_RIGHT, FALSE);
|
||||
|
||||
//----- Create the status bar -----//
|
||||
statusBar.set_has_resize_grip();
|
||||
baseContainer.pack_start(statusBar, PACK_SHRINK);
|
||||
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
} // namespace workspace
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ class WorkspaceWindow : public Gtk::Window
|
|||
{
|
||||
public:
|
||||
WorkspaceWindow(lumiera::gui::model::Project *source_project);
|
||||
virtual ~WorkspaceWindow();
|
||||
|
||||
~WorkspaceWindow();
|
||||
|
||||
private:
|
||||
void create_ui();
|
||||
|
|
@ -68,18 +69,22 @@ private:
|
|||
/* ===== UI ===== */
|
||||
private:
|
||||
Glib::RefPtr<Gtk::UIManager> uiManager;
|
||||
Gtk::VBox base_container;
|
||||
Gtk::HBox dock_container;
|
||||
Gtk::VBox baseContainer;
|
||||
Gtk::HBox dockContainer;
|
||||
|
||||
//----- Dock Frame -----//
|
||||
Gtk::Widget *dock;
|
||||
Gtk::Widget *dockbar;
|
||||
GdlDockLayout *layout;
|
||||
|
||||
//----- Status Bar -----//
|
||||
Gtk::Statusbar statusBar;
|
||||
|
||||
/* ===== Panels ===== */
|
||||
private:
|
||||
AssetsPanel *assets_panel;
|
||||
ViewerPanel *viewer_panel;
|
||||
TimelinePanel *timeline_panel;
|
||||
AssetsPanel *assetsPanel;
|
||||
ViewerPanel *viewerPanel;
|
||||
TimelinePanel *timelinePanel;
|
||||
|
||||
/* ===== Helpers ===== */
|
||||
private:
|
||||
|
|
|
|||
BIN
wiki/draw/LumiLogo.png
Normal file
BIN
wiki/draw/LumiLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
|
|
@ -2150,16 +2150,16 @@ This distributed wiki might be used instead the pipapo.org wiki, investigate tha
|
|||
Wiki works. It is simple to use and just flexible enough to handle the task. I don't go to install any other software for such tasks on my server. While the design progresses I'd propose to move our work into git repositories and eventually phase this wiki pages out anyways. I'd rather like to start out distributed/git right away .. but git gives us only a fine storage layer, for a design process we need some good presentation layer (later when using git and starting the implementation everyones favorite editor serves for that) I have no better ideas yet to solve the presentation problem other than using this wiki (or maybe Bouml).
|
||||
</pre>
|
||||
</div>
|
||||
<div title="LumieraWiki" modifier="Ichthyostega" modified="200805200606" created="200706172308" tags="portal" changecount="34">
|
||||
<pre>This is the entry point to several [[TiddlyWiki]]-Pages containing the developer and design documentation for Lumiera.
|
||||
<div title="LumieraWiki" modifier="Ichthyostega" modified="200808280150" created="200706172308" tags="portal" changecount="41">
|
||||
<pre>[<img[draw/LumiLogo.png]]
|
||||
|
||||
* Cehteh started GitNotes where we will collect some information about git, howto and special setups
|
||||
* since we prefer gpg signed tags in git and not each developer knows gpg well here is a Micro-GPG-HowTo
|
||||
|
||||
''Lumiera'' is the emerging professional non linear video editor for Linux
|
||||
|
||||
This is the entry point to several [[TiddlyWiki]]-Pages containing the developer and design documentation.
|
||||
* we maintain (semi-) final design docs in DesignDocumentation
|
||||
* Things get often worked out on IRC, see IRC-Transcripts for decisions made there and not yet put into the proper documentation places
|
||||
|
||||
Please __end your tiddlers in a newline__, this makes merging in git easier since the /pre tag used in tiddlywiki will become on a single line.
|
||||
|
||||
----
|
||||
!Architecture and Subsystems
|
||||
to get started, we create design drafts emphasizing different aspects and regions of Lumiera
|
||||
|
|
|
|||
Loading…
Reference in a new issue