Eben said 7px padding, not 6.

Eben said 7px padding, not 6.

${
import math

def my_floor(num):
    return int(math.floor(num))

def my_ceil(num):
    return int(math.ceil(num))

# Should we set the line width in the engine to 2.25, and draw non pixel aligned lines?
# Are these already the correct sizes for the XO?

# These sizes need to be sanity checked ...
if theme == "sugar-xo":
    xo = True
    line_width = 2.25       # 2.25
    thick_line_width = 3.5  # 3.5
    subcell_size = 15
    bullet_size = 9.5
    font_height = 24
    default_padding = 7
else: # About 50% smaller
    xo = False
    line_width = 1.125
    thick_line_width = 1.75
    subcell_size = 7
    bullet_size = 5
    font_height = 12
    default_padding = 3

radio_size = my_floor(subcell_size + bullet_size + line_width)
scale_slider_width = my_floor(2 * subcell_size + line_width)
thickness = my_ceil(line_width)

# Colors:

black = '"#000000"'
toolbar_grey = '"#404040"'
button_grey = '"#808080"'
selection_grey = '"#A6A6A6"'
panel_grey = '"#C0C0C0"'
text_field_grey = '"#E5E5E5"'
white = '"#FFFFFF"'

}
style "default"
{
    # Will be overriden in some widgets
    color["focus_line"] = $white

    bg[NORMAL] = $button_grey
    bg[PRELIGHT] = $button_grey
    bg[ACTIVE] = $white
    bg[SELECTED] = $text_field_grey

    fg[NORMAL]        = $black
    fg[ACTIVE]        = $black
    fg[SELECTED]      = $white
    fg[PRELIGHT]      = $white

    text[NORMAL] = $black # button_grey? 1. need to patch GTK+ to use ACTIVE when focused, 2. what color should this really be?
    text[ACTIVE] = $black
    text[SELECTED] = $black
    text[PRELIGHT] = $black

    base[NORMAL] = $text_field_grey
    base[ACTIVE] = $white
    base[SELECTED] = $selection_grey
    base[PRELIGHT] = $white

    fg[INSENSITIVE] = $button_grey
    text[INSENSITIVE] = $button_grey

    xthickness = $thickness
    ythickness = $thickness

    # A lot of these will probably need to be changed, but this has to
    # be done when the exact sizes are known
    GtkWidget::interior-focus = 0
    GtkWidget::focus-line-width = 1   # This does not do anything really
    GtkWidget::focus-padding = 0
    # 0.05 works good for both the sugar and sugar-xo themes
    GtkWidget::cursor-aspect-ratio = 0.05

    GtkWidget::wide-separators = 0
    GtkWidget::separator-height = $thickness
    GtkWidget::separator-width = $thickness

    GtkRange::activate-slider = 1
    GtkButton::inner-border = { 6, 6, 6, 6 }           # ??

    GtkButton::default-border = { 1, 1, 1, 1 }         # line_width - focus-line-width
    GtkButton::default-outside-border = { 2, 2, 2, 2 } # focus-line-width

    GtkScrolledWindow::scrollbar-spacing = 0

    GtkExpander::expander-size = 24
    GtkExpander::expander-spacing = 2     # XXX

    GtkTreeView::expander-size = 24

    GtkArrow::arrow-size = 1.0

    GtkToolbar::shadow-type = GTK_SHADOW_NONE

    GtkProgressBar::min-horizontal-bar-height = $subcell_size
    GtkProgressBar::min-vertical-bar-width = $subcell_size

    engine "sugar" {
        line_width = $line_width
        thick_line_width = $thick_line_width

        # Not sure about this one, but it is not that important
        max_radius = $( 2*subcell_size )
    }
}

#############################################################
# Styles that set default background/foreground colors
#
#  We almost always need two styles because of the X windows.
#  For example bg[NORMAL] of a window (or eventbox) needs to
#  be set to be the correct window color so that X fills the
#  window correctly from the beginning, and it does not
#  flash in the wrong color.
#############################################################

style "window"
{
    bg[NORMAL] = $panel_grey
}

style "window-child"
{
    bg[INSENSITIVE] = $panel_grey
    base[INSENSITIVE] = $panel_grey

    fg[NORMAL] = $black

    engine "sugar" {
        label_fg_color = $black
    }
}

style "groupbox-panel"
{
    bg[NORMAL] = $selection_grey
}

style "groupbox-panel-child"
{
    bg[INSENSITIVE] = $selection_grey
    base[INSENSITIVE] = $selection_grey

    fg[NORMAL] = $white

    engine "sugar" {
        label_fg_color = $white
    }
}

style "groupbox-palette"
{
    bg[NORMAL] = $toolbar_grey
}

style "groupbox-palette-child"
{
    bg[INSENSITIVE] = $toolbar_grey
    base[INSENSITIVE] = $toolbar_grey

    fg[NORMAL] = $white

    engine "sugar" {
        label_fg_color = $white
    }
}

style "menu"
{
    bg[NORMAL] = $black
    bg[ACTIVE] = $button_grey

    GtkMenu::horizontal-padding = 0
    GtkMenu::vertical-padding   = 0

    xthickness = 0
    ythickness = 0
}

# Can this all be moved in the menuitem style?
style "menu-child"
{
    color["bg_color"] = $black

    fg[NORMAL]   = $white
    fg[PRELIGHT] = $white

    # Work around bug #382646
    text[NORMAL]   = $white
    text[PRELIGHT] = $white

    bg[NORMAL] = $button_grey

    bg[INSENSITIVE] = $black
    base[INSENSITIVE] = $black

    engine "sugar" {
        label_fg_color = $white
    }
}

#########################################################
#########################################################

style "scrollbar"
{
    GtkScrollbar::slider-width = 16    # ?
    GtkScrollbar::trough-border = 0
    GtkScrollbar::stepper-spacing = 0
    GtkScrollbar::min-slider-length = 30    # ?
    GtkScrollbar::has-forward-stepper = 0
    GtkScrollbar::has-backward-stepper = 0
    GtkScrollbar::has-secondary-forward-stepper = 0
    GtkScrollbar::has-secondary-backward-stepper = 0

    # Hack for mozilla as it does not obey the above style properties ...
    # Really, mozilla should be fixed ...
    GtkScrollbar::stepper-size = 1
}

# hints for the trough padding hacks
# We cannot go trough GTK+, as we don't want a padding on all sides, but only one
# If we wanted padding on all sides, trough-border would work great.
style "hscrollbar" = "scrollbar"
{
    engine "sugar" {
        hint = "hscrollbar"
        # Rounded, not floating point value. maybe change this?
        scrollbar_border = $thickness
    }
}

style "vscrollbar" = "scrollbar"
{
    engine "sugar" {
        hint = "vscrollbar"
        scrollbar_border = $thickness
    }
}

style "scale"
{
    GtkWidget::focus-line-width = 0

    bg[NORMAL] = "#808080"

    # "square" slider (really round of course)
    # Same as indicator-size?
    GtkRange::slider-width = $scale_slider_width
    GtkScale::slider-length = $scale_slider_width
    GtkRange::trough-border = 0
    GtkRange::stepper-spacing = 0
    GtkRange::trough-side-details = 1
}

# hints for the trough sizing hacks
style "hscale" = "scale"
{
    engine "sugar" {
        hint = "hscale"
    }
}

style "vscale" = "scale"
{
    engine "sugar" {
        hint = "vscale"
    }
}

style "spinbutton"
{
    bg[NORMAL]  = $button_grey
    bg[ACTIVE]  = $white
    fg[NORMAL]  = $white
    fg[ACTIVE]  = $black

    engine "sugar" {
        hint = "spinbutton"
    }
}

style "comboboxentry"
{
    # Copied from the "default" style. Part of the workaround for bug #382646.
    text[NORMAL] = $black
    text[ACTIVE] = $black
    text[SELECTED] = $black
    text[PRELIGHT] = $black

    engine "sugar" {
        hint = "comboboxentry"
    }
}

style "frame"
{
    bg[NORMAL] = $toolbar_grey
}

style "notebook"
{
    GtkNotebook::tab-overlap = -2

    xthickness = 0
    ythickness = 0

    bg[ACTIVE] = $button_grey
}

style "toolbutton"
{
    color["focus_line"] = $black

    bg[PRELIGHT] = $black
    bg[ACTIVE] = $button_grey
    bg[NORMAL] = $black

    fg[NORMAL] = $white
    fg[ACTIVE] = $white
    fg[PRELIGHT] = $white

    engine "sugar" {
        max_radius = 5.0
	fake_padding = $default_padding
    }
}

style "toolbox"
{
    fg[NORMAL] = $white
    fg[ACTIVE] = $white

    bg[NORMAL] = $toolbar_grey
    bg[INSENSITIVE] = $toolbar_grey
    base[INSENSITIVE] = $toolbar_grey
}

style "panel"
{
    bg[NORMAL] = $panel_grey
    fg[NORMAL] = $black
}

style "entry"
{
    # small inner border and a large x/ythickness for entries
    # to reduce the number of hacks needed :-)
    xthickness = $(thickness*3)
    ythickness = $(thickness*3)

    # This tries to get a height of exactly 45 pixel for the entry.
    GtkEntry::inner-border = { $(max(subcell_size - thickness*3, 0)), $(max(subcell_size - thickness*3, 0)),
                               $(max(my_floor((3*subcell_size - font_height - thickness*3*2)/2),0)), $(max(my_ceil((3*subcell_size - font_height - thickness*3*2)/2), 0)) }

    GtkWidget::focus-line-width = 0
}

style "button"
{
    fg[NORMAL]  = $white

    bg[NORMAL] = $button_grey
}

style "combobox"
{
    # Work around GTK+ bug #382646
    text[NORMAL]      = $white
    text[ACTIVE]      = $white
    text[PRELIGHT]    = $white
}

style "checkbutton"
{
    base[NORMAL]      = $white
    base[PRELIGHT]    = $white
    base[ACTIVE]      = $text_field_grey

    text[PRELIGHT]    = $toolbar_grey
    text[NORMAL]      = $toolbar_grey
    text[ACTIVE]      = $toolbar_grey

    # I won't get the exact sizing, but this should be pretty close
    GtkCheckButton::indicator-size = $radio_size
    GtkCheckButton::indicator-spacing = 3
    GtkWidget::focus-padding = 3

    engine "sugar" {
        # Reset the colors to the normal color again
        # as they were overriden by the button style
        fg[NORMAL]        = label_fg_color
        fg[PRELIGHT]      = label_fg_color
        fg[ACTIVE]        = label_fg_color
    }
}

style "progressbar"
{
    xthickness = 0
    ythickness = 0
}

style "menuitem"
{
    GtkCheckMenuItem::indicator-size = $radio_size

    bg[PRELIGHT] = $button_grey

    text[PRELIGHT]    = $white
    text[NORMAL]      = $white
    text[ACTIVE]      = $white

    GtkMenuItem::horizontal-padding = $line_width
    xthickness = $(my_ceil(line_width * 2))
    ythickness = $thickness
}

style "checkmenuitem"
{
    # This style is only there because of bug #382646 ...
    base[NORMAL]      = $white
    base[PRELIGHT]    = $white
    base[ACTIVE]      = $text_field_grey

    text[PRELIGHT]    = $toolbar_grey
    text[NORMAL]      = $toolbar_grey
    text[ACTIVE]      = $toolbar_grey
}

style "separatormenuitem"
{
    GtkMenuItem::horizontal-padding = 0
    xthickness = 0
}

####################################################################
# Default style, setting some generic options and style properties
####################################################################
class "GtkWidget" style "default"

####################################################################
# Styles that apply the different background (and foreground) colors
####################################################################

# This one should probably be the default (ie. no window-child style)
widget_class "<GtkWindow>"               style "window"
widget_class "<GtkWindow>*<GtkEventBox>" style "window"
widget_class "<GtkWindow>*"              style "window-child"

# SugarToolbox
#widget_class "*<SugarToolbox>" style "toolbox"
#widget_class "*<SugarToolbox>*" style "toolbox-child"
#widget_class "*<SugarToolbox>*<GtkEventBox>" style "toolbox"
widget_class "*<SugarToolbox>*"        style "toolbox"
widget_class "*<GtkToolbar>*"          style "toolbox"

# SugarPalette
widget_class "<SugarPalette>"          style "menu"
widget_class "<SugarPalette>.*"        style "menu-child"

# SugarFrameWindow
widget_class "*<SugarFrameWindow>*"    style "frame"

# SugarPanel
widget_class "*<SugarPanel>*"          style "panel"

# GroupBoxes (don't set bg[NORMAL] on the widget itself)
widget_class "<GtkWindow>*<SugarGroupBox>*<GtkEventBox>" style "groupbox-panel"
widget_class "<GtkWindow>*<SugarGroupBox>*"   style "groupbox-panel-child"

widget_class "<SugarPalette>*<SugarGroupBox>*<GtkEventBox>" style "groupbox-palette"
widget_class "<SugarPalette>*<SugarGroupBox>*"   style "groupbox-palette-child"

####################################################################
# Normal widget styles, using the above things
####################################################################
# The following only uses widget_class matches to get the priority
# right. An alternative would be to lower the priority of the
# background matches (which need widget_class) to eg. "application"

# Menu
widget_class "*<GtkMenuShell>"            style "menu"               # Why is this menu shell?
widget_class "*<GtkMenuShell>.*"          style "menu-child"         # Why is this menu shell?
widget_class "*<GtkMenuItem>*"            style "menuitem"
widget_class "*<GtkCheckMenuItem>"        style "checkmenuitem"
widget_class "*<GtkSeparatorMenuItem>*"   style "separatormenuitem"

# Buttons and Combos
widget_class "*<GtkComboBox>*"         style "combobox"
widget_class "*<GtkComboBoxEntry>*"    style "comboboxentry"
widget_class "*<GtkCombo>*"            style "comboboxentry"
widget_class "*<GtkButton>*"           style "button"
widget_class "*<GtkCheckButton>*"      style "checkbutton"

# Entries
widget_class "*<GtkEntry>"       style "entry"
widget_class "*<GtkSpinButton>"  style "spinbutton"

# Misc widgets
widget_class "*<GtkNotebook>"    style "notebook"
widget_class "*<GtkHScrollbar>"  style "hscrollbar"
widget_class "*<GtkVScrollbar>"  style "vscrollbar"
widget_class "*<GtkHScale>"      style "hscale"
widget_class "*<GtkVScale>"      style "vscale"
widget_class "*<GtkProgressBar>" style "progressbar"

# Toolbar
widget_class "*<GtkToolButton>*"          style "toolbutton"

${
import math

def my_floor(num):
    return int(math.floor(num))

def my_ceil(num):
    return int(math.ceil(num))

# Should we set the line width in the engine to 2.25, and draw non pixel aligned lines?
# Are these already the correct sizes for the XO?

# These sizes need to be sanity checked ...
if theme == "sugar-xo":
    xo = True
    line_width = 2.25       # 2.25
    thick_line_width = 3.5  # 3.5
    subcell_size = 15
    bullet_size = 9.5
    font_height = 24
    default_padding = 6
else: # About 50% smaller
    xo = False
    line_width = 1.125
    thick_line_width = 1.75
    subcell_size = 7
    bullet_size = 5
    font_height = 12
    default_padding = 3

radio_size = my_floor(subcell_size + bullet_size + line_width)
scale_slider_width = my_floor(2 * subcell_size + line_width)
thickness = my_ceil(line_width)

# Colors:

black = '"#000000"'
toolbar_grey = '"#404040"'
button_grey = '"#808080"'
selection_grey = '"#A6A6A6"'
panel_grey = '"#C0C0C0"'
text_field_grey = '"#E5E5E5"'
white = '"#FFFFFF"'

}
style "default"
{
    # Will be overriden in some widgets
    color["focus_line"] = $white

    bg[NORMAL] = $button_grey
    bg[PRELIGHT] = $button_grey
    bg[ACTIVE] = $white
    bg[SELECTED] = $text_field_grey

    fg[NORMAL]        = $black
    fg[ACTIVE]        = $black
    fg[SELECTED]      = $white
    fg[PRELIGHT]      = $white

    text[NORMAL] = $black # button_grey? 1. need to patch GTK+ to use ACTIVE when focused, 2. what color should this really be?
    text[ACTIVE] = $black
    text[SELECTED] = $black
    text[PRELIGHT] = $black

    base[NORMAL] = $text_field_grey
    base[ACTIVE] = $white
    base[SELECTED] = $selection_grey
    base[PRELIGHT] = $white

    fg[INSENSITIVE] = $button_grey
    text[INSENSITIVE] = $button_grey

    xthickness = $thickness
    ythickness = $thickness

    # A lot of these will probably need to be changed, but this has to
    # be done when the exact sizes are known
    GtkWidget::interior-focus = 0
    GtkWidget::focus-line-width = 1   # This does not do anything really
    GtkWidget::focus-padding = 0
    # 0.05 works good for both the sugar and sugar-xo themes
    GtkWidget::cursor-aspect-ratio = 0.05

    GtkWidget::wide-separators = 0
    GtkWidget::separator-height = $thickness
    GtkWidget::separator-width = $thickness

    GtkRange::activate-slider = 1
    GtkButton::inner-border = { 6, 6, 6, 6 }           # ??

    GtkButton::default-border = { 1, 1, 1, 1 }         # line_width - focus-line-width
    GtkButton::default-outside-border = { 2, 2, 2, 2 } # focus-line-width

    GtkScrolledWindow::scrollbar-spacing = 0

    GtkExpander::expander-size = 24
    GtkExpander::expander-spacing = 2     # XXX

    GtkTreeView::expander-size = 24

    GtkArrow::arrow-size = 1.0

    GtkToolbar::shadow-type = GTK_SHADOW_NONE

    GtkProgressBar::min-horizontal-bar-height = $subcell_size
    GtkProgressBar::min-vertical-bar-width = $subcell_size

    engine "sugar" {
        line_width = $line_width
        thick_line_width = $thick_line_width

        # Not sure about this one, but it is not that important
        max_radius = $( 2*subcell_size )
    }
}

#############################################################
# Styles that set default background/foreground colors
#
#  We almost always need two styles because of the X windows.
#  For example bg[NORMAL] of a window (or eventbox) needs to
#  be set to be the correct window color so that X fills the
#  window correctly from the beginning, and it does not
#  flash in the wrong color.
#############################################################

style "window"
{
    bg[NORMAL] = $panel_grey
}

style "window-child"
{
    bg[INSENSITIVE] = $panel_grey
    base[INSENSITIVE] = $panel_grey

    fg[NORMAL] = $black

    engine "sugar" {
        label_fg_color = $black
    }
}

style "groupbox-panel"
{
    bg[NORMAL] = $selection_grey
}

style "groupbox-panel-child"
{
    bg[INSENSITIVE] = $selection_grey
    base[INSENSITIVE] = $selection_grey

    fg[NORMAL] = $white

    engine "sugar" {
        label_fg_color = $white
    }
}

style "groupbox-palette"
{
    bg[NORMAL] = $toolbar_grey
}

style "groupbox-palette-child"
{
    bg[INSENSITIVE] = $toolbar_grey
    base[INSENSITIVE] = $toolbar_grey

    fg[NORMAL] = $white

    engine "sugar" {
        label_fg_color = $white
    }
}

style "menu"
{
    bg[NORMAL] = $black
    bg[ACTIVE] = $button_grey

    GtkMenu::horizontal-padding = 0
    GtkMenu::vertical-padding   = 0

    xthickness = 0
    ythickness = 0
}

# Can this all be moved in the menuitem style?
style "menu-child"
{
    color["bg_color"] = $black

    fg[NORMAL]   = $white
    fg[PRELIGHT] = $white

    # Work around bug #382646
    text[NORMAL]   = $white
    text[PRELIGHT] = $white

    bg[NORMAL] = $button_grey

    bg[INSENSITIVE] = $black
    base[INSENSITIVE] = $black

    engine "sugar" {
        label_fg_color = $white
    }
}

#########################################################
#########################################################

style "scrollbar"
{
    GtkScrollbar::slider-width = 16    # ?
    GtkScrollbar::trough-border = 0
    GtkScrollbar::stepper-spacing = 0
    GtkScrollbar::min-slider-length = 30    # ?
    GtkScrollbar::has-forward-stepper = 0
    GtkScrollbar::has-backward-stepper = 0
    GtkScrollbar::has-secondary-forward-stepper = 0
    GtkScrollbar::has-secondary-backward-stepper = 0

    # Hack for mozilla as it does not obey the above style properties ...
    # Really, mozilla should be fixed ...
    GtkScrollbar::stepper-size = 1
}

# hints for the trough padding hacks
# We cannot go trough GTK+, as we don't want a padding on all sides, but only one
# If we wanted padding on all sides, trough-border would work great.
style "hscrollbar" = "scrollbar"
{
    engine "sugar" {
        hint = "hscrollbar"
        # Rounded, not floating point value. maybe change this?
        scrollbar_border = $thickness
    }
}

style "vscrollbar" = "scrollbar"
{
    engine "sugar" {
        hint = "vscrollbar"
        scrollbar_border = $thickness
    }
}

style "scale"
{
    GtkWidget::focus-line-width = 0

    bg[NORMAL] = "#808080"

    # "square" slider (really round of course)
    # Same as indicator-size?
    GtkRange::slider-width = $scale_slider_width
    GtkScale::slider-length = $scale_slider_width
    GtkRange::trough-border = 0
    GtkRange::stepper-spacing = 0
    GtkRange::trough-side-details = 1
}

# hints for the trough sizing hacks
style "hscale" = "scale"
{
    engine "sugar" {
        hint = "hscale"
    }
}

style "vscale" = "scale"
{
    engine "sugar" {
        hint = "vscale"
    }
}

style "spinbutton"
{
    bg[NORMAL]  = $button_grey
    bg[ACTIVE]  = $white
    fg[NORMAL]  = $white
    fg[ACTIVE]  = $black

    engine "sugar" {
        hint = "spinbutton"
    }
}

style "comboboxentry"
{
    # Copied from the "default" style. Part of the workaround for bug #382646.
    text[NORMAL] = $black
    text[ACTIVE] = $black
    text[SELECTED] = $black
    text[PRELIGHT] = $black

    engine "sugar" {
        hint = "comboboxentry"
    }
}

style "frame"
{
    bg[NORMAL] = $toolbar_grey
}

style "notebook"
{
    GtkNotebook::tab-overlap = -2

    xthickness = 0
    ythickness = 0

    bg[ACTIVE] = $button_grey
}

style "toolbutton"
{
    color["focus_line"] = $black

    bg[PRELIGHT] = $black
    bg[ACTIVE] = $button_grey
    bg[NORMAL] = $black

    fg[NORMAL] = $white
    fg[ACTIVE] = $white
    fg[PRELIGHT] = $white

    engine "sugar" {
        max_radius = 5.0
	fake_padding = $default_padding
    }
}

style "toolbox"
{
    fg[NORMAL] = $white
    fg[ACTIVE] = $white

    bg[NORMAL] = $toolbar_grey
    bg[INSENSITIVE] = $toolbar_grey
    base[INSENSITIVE] = $toolbar_grey
}

style "panel"
{
    bg[NORMAL] = $panel_grey
    fg[NORMAL] = $black
}

style "entry"
{
    # small inner border and a large x/ythickness for entries
    # to reduce the number of hacks needed :-)
    xthickness = $(thickness*3)
    ythickness = $(thickness*3)

    # This tries to get a height of exactly 45 pixel for the entry.
    GtkEntry::inner-border = { $(max(subcell_size - thickness*3, 0)), $(max(subcell_size - thickness*3, 0)),
                               $(max(my_floor((3*subcell_size - font_height - thickness*3*2)/2),0)), $(max(my_ceil((3*subcell_size - font_height - thickness*3*2)/2), 0)) }

    GtkWidget::focus-line-width = 0
}

style "button"
{
    fg[NORMAL]  = $white

    bg[NORMAL] = $button_grey
}

style "combobox"
{
    # Work around GTK+ bug #382646
    text[NORMAL]      = $white
    text[ACTIVE]      = $white
    text[PRELIGHT]    = $white
}

style "checkbutton"
{
    base[NORMAL]      = $white
    base[PRELIGHT]    = $white
    base[ACTIVE]      = $text_field_grey

    text[PRELIGHT]    = $toolbar_grey
    text[NORMAL]      = $toolbar_grey
    text[ACTIVE]      = $toolbar_grey

    # I won't get the exact sizing, but this should be pretty close
    GtkCheckButton::indicator-size = $radio_size
    GtkCheckButton::indicator-spacing = 3
    GtkWidget::focus-padding = 3

    engine "sugar" {
        # Reset the colors to the normal color again
        # as they were overriden by the button style
        fg[NORMAL]        = label_fg_color
        fg[PRELIGHT]      = label_fg_color
        fg[ACTIVE]        = label_fg_color
    }
}

style "progressbar"
{
    xthickness = 0
    ythickness = 0
}

style "menuitem"
{
    GtkCheckMenuItem::indicator-size = $radio_size

    bg[PRELIGHT] = $button_grey

    text[PRELIGHT]    = $white
    text[NORMAL]      = $white
    text[ACTIVE]      = $white

    GtkMenuItem::horizontal-padding = $line_width
    xthickness = $(my_ceil(line_width * 2))
    ythickness = $thickness
}

style "checkmenuitem"
{
    # This style is only there because of bug #382646 ...
    base[NORMAL]      = $white
    base[PRELIGHT]    = $white
    base[ACTIVE]      = $text_field_grey

    text[PRELIGHT]    = $toolbar_grey
    text[NORMAL]      = $toolbar_grey
    text[ACTIVE]      = $toolbar_grey
}

style "separatormenuitem"
{
    GtkMenuItem::horizontal-padding = 0
    xthickness = 0
}

####################################################################
# Default style, setting some generic options and style properties
####################################################################
class "GtkWidget" style "default"

####################################################################
# Styles that apply the different background (and foreground) colors
####################################################################

# This one should probably be the default (ie. no window-child style)
widget_class "<GtkWindow>"               style "window"
widget_class "<GtkWindow>*<GtkEventBox>" style "window"
widget_class "<GtkWindow>*"              style "window-child"

# SugarToolbox
#widget_class "*<SugarToolbox>" style "toolbox"
#widget_class "*<SugarToolbox>*" style "toolbox-child"
#widget_class "*<SugarToolbox>*<GtkEventBox>" style "toolbox"
widget_class "*<SugarToolbox>*"        style "toolbox"
widget_class "*<GtkToolbar>*"          style "toolbox"

# SugarPalette
widget_class "<SugarPalette>"          style "menu"
widget_class "<SugarPalette>.*"        style "menu-child"

# SugarFrameWindow
widget_class "*<SugarFrameWindow>*"    style "frame"

# SugarPanel
widget_class "*<SugarPanel>*"          style "panel"

# GroupBoxes (don't set bg[NORMAL] on the widget itself)
widget_class "<GtkWindow>*<SugarGroupBox>*<GtkEventBox>" style "groupbox-panel"
widget_class "<GtkWindow>*<SugarGroupBox>*"   style "groupbox-panel-child"

widget_class "<SugarPalette>*<SugarGroupBox>*<GtkEventBox>" style "groupbox-palette"
widget_class "<SugarPalette>*<SugarGroupBox>*"   style "groupbox-palette-child"

####################################################################
# Normal widget styles, using the above things
####################################################################
# The following only uses widget_class matches to get the priority
# right. An alternative would be to lower the priority of the
# background matches (which need widget_class) to eg. "application"

# Menu
widget_class "*<GtkMenuShell>"            style "menu"               # Why is this menu shell?
widget_class "*<GtkMenuShell>.*"          style "menu-child"         # Why is this menu shell?
widget_class "*<GtkMenuItem>*"            style "menuitem"
widget_class "*<GtkCheckMenuItem>"        style "checkmenuitem"
widget_class "*<GtkSeparatorMenuItem>*"   style "separatormenuitem"

# Buttons and Combos
widget_class "*<GtkComboBox>*"         style "combobox"
widget_class "*<GtkComboBoxEntry>*"    style "comboboxentry"
widget_class "*<GtkCombo>*"            style "comboboxentry"
widget_class "*<GtkButton>*"           style "button"
widget_class "*<GtkCheckButton>*"      style "checkbutton"

# Entries
widget_class "*<GtkEntry>"       style "entry"
widget_class "*<GtkSpinButton>"  style "spinbutton"

# Misc widgets
widget_class "*<GtkNotebook>"    style "notebook"
widget_class "*<GtkHScrollbar>"  style "hscrollbar"
widget_class "*<GtkVScrollbar>"  style "vscrollbar"
widget_class "*<GtkHScale>"      style "hscale"
widget_class "*<GtkVScale>"      style "vscale"
widget_class "*<GtkProgressBar>" style "progressbar"

# Toolbar
widget_class "*<GtkToolButton>*"          style "toolbutton"


add ADS to PSOURCES for EM platform

add ADS to PSOURCES for EM platform

#-*-Makefile-*- vim:syntax=make
#
# Copyright (c) 2008-2012 the MansOS team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#  * Redistributions of source code must retain the above copyright notice,
#    this list of  conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

#############################################
# Energy Measuring board
#############################################

#############################################
# Define platform variables

ARCH = msp430
MCU_MODEL = msp430f1611

# Upload target specifically for EM board
UPLOAD_TARGET=upload-em

# Default clock speed: 1MHz
ifeq ($(USE_HARDWARE_TIMERS),y)
CPU_MHZ ?= 4
else
CPU_MHZ ?= 1  # actually the default DCO frequency is around 800 kHz
endif

CFLAGS += -DPLATFORM_EM=1

#############################################
# Define platform-specific sources
# (excluding architecture-specific sources)

PSOURCES += $(MOS)/platforms/em/platform.c
PSOURCES += $(MOS)/chips/msp430/msp430x1xx_clock.c
PSOURCES-$(USE_ADS1115) += $(MOS)/chips/ads1115/ads1115.c


fix generation command and output targets

@[if DEVELSPACE]@
# base dir in develspace
set(dynamic_reconfigure_BASE_DIR @(CMAKE_CURRENT_SOURCE_DIR))
@[else]@
# base dir in installspace
set(dynamic_reconfigure_BASE_DIR @(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION))
@[end if]@

macro(generate_dynamic_reconfigure_options)
  if(${PROJECT_NAME}_CATKIN_PACKAGE)
    message(FATAL_ERROR "generate_dynamic_reconfigure_options() must be called before catkin_package() in project '${PROJECT_NAME}'")
  endif()

  # ensure that package destination variables are defined
  catkin_destinations()

  set(_autogen "")
  foreach(_cfg ${ARGN})
    # Construct the path to the .cfg file
    set(_input ${PROJECT_SOURCE_DIR}/${_cfg})

    # The .cfg file is its own generator.
    set(gencfg_build_files
      ${dynamic_reconfigure_BASE_DIR}/templates/ConfigType.py
      ${dynamic_reconfigure_BASE_DIR}/templates/ConfigType.h
    )

    get_filename_component(_cfgonly ${_cfg} NAME_WE)
    set(_output_cpp ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}/${_cfgonly}Config.h)
    set(_output_py ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/${_cfgonly}Config.py)
    set(_output_dox ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfgonly}Config.dox)
    set(_output_wikidoc ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfgonly}Config.wikidoc)
    set(_output_usage ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfgonly}Config-usage.dox)

    assert(CATKIN_ENV)
    set(_cmd ${CATKIN_ENV}
      ${_input}
      ${dynamic_reconfigure_BASE_DIR}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}
    )
    debug_message(2 "dynamic reconfigure cmd: ${_cmd}")
    execute_process(COMMAND ${_cmd}
                    RESULT_VARIABLE RES_VAR
                    OUTPUT_VARIABLE OUT_VAR
                    ERROR_VARIABLE ERR_VAR
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_STRIP_TRAILING_WHITESPACE
    )
    if(${RES_VAR} OR NOT "${ERR_VAR}" STREQUAL "")
      message(FATAL_ERROR "Could not run dynamic reconfigure file '${_cfg}': ${ERR_VAR}")
    endif()
    message(STATUS "dynamic_reconfigure built ${_cfg}: ${OUT_VAR}")

    #file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py)

    add_custom_command(OUTPUT
      ${_output_cpp} ${_output_dox} ${_output_usage} ${_output_py} ${_output_wikidoc}
      COMMAND ${_cmd}
      DEPENDS ${_input} ${gencfg_build_files}
      COMMENT "Generating dynamic reconfigure files from ${_cfg}: ${_output_cpp} ${_output_py}"
    )

    list(APPEND ${PROJECT_NAME}_generated
      ${_output_cpp} ${_output_py}
    )

    install(FILES ${_output_cpp}
            DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
  endforeach(_cfg)

  # gencfg target for hard dependency od dynamic_reconfigure generation
  add_custom_target(${PROJECT_NAME}_gencfg DEPENDS ${${PROJECT_NAME}_generated})

  dynreconf_called()
endmacro()

macro(dynreconf_called)
  if(NOT dynamic_reconfigure_CALLED)
    set(dynamic_reconfigure_CALLED TRUE)

    # mark that generate_dynamic_reconfigure_options() was called in order to detect wrong order of calling with catkin_python_setup()
    set(${PROJECT_NAME}_GENERATE_DYNAMIC_RECONFIGURE TRUE)
    # check if catkin_python_setup() was called in order to skip installation of generated __init__.py file
    set(package_has_static_sources ${${PROJECT_NAME}_CATKIN_PYTHON_SETUP})

    # generate empty __init__ to make parent folder of msg/srv a python module
    if(NOT EXISTS ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py)
      file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py "")
    endif()
    if(NOT package_has_static_sources)
      # install package __init__.py
      install(
        FILES ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py
        DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
      )
    endif()

    # make sure we can find generated messages and that they overlay all other includes
    include_directories(BEFORE ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION})
    # pass the include directory to catkin_package()
    list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION})

    # generate cfg module __init__.py
    if(NOT EXISTS ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py)
      file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py "")
    endif()

    # compile python code before installing
    find_package(PythonInterp REQUIRED)
    install(CODE "execute_process(COMMAND \"${PYTHON_EXECUTABLE}\" -m compileall \"${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg\")")
    install(
      DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg
      DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
    )
  endif()
endmacro()

@[if DEVELSPACE]@
# base dir in develspace
set(dynamic_reconfigure_BASE_DIR @(CMAKE_CURRENT_SOURCE_DIR))
@[else]@
# base dir in installspace
set(dynamic_reconfigure_BASE_DIR @(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION))
@[end if]@

macro(generate_dynamic_reconfigure_options)
  if(${PROJECT_NAME}_CATKIN_PACKAGE)
    message(FATAL_ERROR "generate_dynamic_reconfigure_options() must be called before catkin_package() in project '${PROJECT_NAME}'")
  endif()

  # ensure that package destination variables are defined
  catkin_destinations()

  set(_autogen "")
  foreach(_cfg ${ARGN})
    # Construct the path to the .cfg file
    set(_input ${PROJECT_SOURCE_DIR}/${_cfg})

    # The .cfg file is its own generator.
    set(gencfg_build_files
      ${dynamic_reconfigure_BASE_DIR}/templates/ConfigType.py
      ${dynamic_reconfigure_BASE_DIR}/templates/ConfigType.h
    )

    get_filename_component(_cfgonly ${_cfg} NAME_WE)
    set(_output_cpp ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}/${_cfgonly}Config.h)
    set(_output_py ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/${_cfgonly}Config.py)
    set(_output_dox ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfg_bare}Config.dox)
    set(_output_wikidoc ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfg_bare}Config.wikidoc)
    set(_output_usage ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_SHARE_DESTINATION}/docs/${_cfg_bare}Config-usage.dox)

    assert(CATKIN_ENV)
    set(_cmd ${CATKIN_ENV}
      ${_input}
      ${dynamic_reconfigure_BASE_DIR}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_BIN_DESTINATION}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}
      ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}
    )
    debug_message(2 "dynamic reconfigure cmd: ${_cmd}")
    execute_process(COMMAND ${_cmd}
                    RESULT_VARIABLE RES_VAR
                    OUTPUT_VARIABLE OUT_VAR
                    ERROR_VARIABLE ERR_VAR
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_STRIP_TRAILING_WHITESPACE
    )
    if(${RES_VAR} OR NOT "${ERR_VAR}" STREQUAL "")
      message(FATAL_ERROR "Could not run dynamic reconfigure file '${_cfg}': ${ERR_VAR}")
    endif()
    message(STATUS "dynamic_reconfigure built ${_cfg}: ${OUT_VAR}")

    #file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py)

    add_custom_command(OUTPUT
      ${_output_cpp} ${_output_dox} ${_output_usage} ${_output_py} ${_output_wikidoc}
      COMMAND ${_cmd}
      DEPENDS ${_input} ${gencfg_build_files}
      COMMENT "Generating dynamic reconfigure files from ${_cfg}: ${_output_cpp} ${_output_py}"
    )

    list(APPEND ${PROJECT_NAME}_generated
      ${_output_cpp} ${_output_py}
    )

    install(FILES ${_output_cpp}
            DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
  endforeach(_cfg)

  # gencfg target for hard dependency od dynamic_reconfigure generation
  add_custom_target(${PROJECT_NAME}_gencfg DEPENDS ${${PROJECT_NAME}_generated})

  dynreconf_called()
endmacro()

macro(dynreconf_called)
  if(NOT dynamic_reconfigure_CALLED)
    set(dynamic_reconfigure_CALLED TRUE)

    # mark that generate_dynamic_reconfigure_options() was called in order to detect wrong order of calling with catkin_python_setup()
    set(${PROJECT_NAME}_GENERATE_DYNAMIC_RECONFIGURE TRUE)
    # check if catkin_python_setup() was called in order to skip installation of generated __init__.py file
    set(package_has_static_sources ${${PROJECT_NAME}_CATKIN_PYTHON_SETUP})

    # generate empty __init__ to make parent folder of msg/srv a python module
    if(NOT EXISTS ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py)
      file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py "")
    endif()
    if(NOT package_has_static_sources)
      # install package __init__.py
      install(
        FILES ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/__init__.py
        DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
      )
    endif()

    # make sure we can find generated messages and that they overlay all other includes
    include_directories(BEFORE ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION})
    # pass the include directory to catkin_package()
    list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION})

    # generate cfg module __init__.py
    if(NOT EXISTS ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py)
      file(WRITE ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg/__init__.py "")
    endif()

    # compile python code before installing
    find_package(PythonInterp REQUIRED)
    install(CODE "execute_process(COMMAND \"${PYTHON_EXECUTABLE}\" -m compileall \"${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg\")")
    install(
      DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}/cfg
      DESTINATION ${CATKIN_PACKAGE_PYTHON_DESTINATION}
    )
  endif()
endmacro()


updated workspace setup

updated workspace setup


Fix restoration of functions by wrapping in parentheses to make them a valid expression to eval.

if (typeof(std.persist) === 'undefined')
    throw new Error('Error.  Do not import this file directly.  Only import it from persistService.em');

(function()
 {

     /**
      Each element of this array contains the unique id given to the
      presence object when it was being persisted.  And each element
      correpsonds to a presence that is trying to be restored in the
      world.
      */
     var allPresStillRest = {};

     var mRestoring = false;

     function registerPresenceStillRestoring(presObjID)
     {
         allPresStillRest[presObjID] = presObjID;
     }

     /**
      Each restored presence has an onConnected callback.  The
      onConnected callback should be generated from this afterRestored
      function.  All that the callback does is update the nameService
      that we're using with the new presence object and removes this
      presence from the list of presences that we are restoring that
      are still waiting to be connected (in allPresStillRest).

      Second stage of restoration (fixing up pointers to other
      objects) waits until all presences have been connected (polls
      allPresStillRest to see if have zero length).

      @param {int} presObjID, unique name that was given to presence
      before restore.  (ie name that goes into nameService.)

      @param nameService nameService used during restoration.
      */
     function afterRestored(presObjID,nameService,cb)
     {
         var returner = function()
         {
             //insert the presence into nameService;
             nameService.insertObjectWithName(system.self,presObjID);
             delete allPresStillRest[presObjID];
             if (Object.keys(allPresStillRest).length == 0)
                 cb(true, null); // Not sure about this being null....
        };
         return returner;
     }

     function checkIsTriplet(toCheck)
     {
         if ((typeof(toCheck) !== 'object') || (!('length' in toCheck)) || (toCheck.length != 3))
             return false;

         return true;
     }

     function tripletGetIndexName(triplet)
     {
         if (!checkIsTriplet(triplet))
         {
             system.prettyprint(triplet);
             throw new Error('Error in tripletGetIndexName.  Requires triplet to be passed in');
         }

         return triplet[0];
     }

     function tripletGetValue(triplet)
     {
         if (!checkIsTriplet(triplet))
             throw new Error('Error in tripletGetValue.  Requires triplet to be passed in');

         var type = tripletGetType(triplet);
         if (type == 'number')
             return parseFloat(triplet[1]);
         if (type == 'string')
             return triplet[1];
         if (type == 'boolean')
             return (triplet[1] == 'true');

         return triplet[1];
     }

     function tripletGetType(triplet)
     {
         if (!checkIsTriplet(triplet))
             throw new Error('Error in tripletGetType.  Requires triplet to be passed in');
         return triplet[2];
     }

    /**
     @param {array} triplet Array containing three values.  Indices of
     array follow:
       0 : index
       1 : value to set to/object pointer/'null'
       2 : type record

     @return {boolean} Returns true if the value in this object is a
     value type
     */
    function tripletIsValueType (triplet)
    {
        if (! checkIsTriplet(triplet))
            throw new Error('Error in checkTripletIsValueType.  Requires triplet to be passed in');

        var tripType = tripletGetType(triplet);

        if ((tripType != 'object') && (tripType != 'function') &&
            (tripType!=std.persist.SYSTEM_TYPE_STRING) &&
            (tripType!=std.persist.PRESENCE_OBJECT_TYPE_STRING) &&
            (tripType!=std.persist.VISIBLE_TYPE_STRING) &&
            (tripType!=std.persist.TIMER_TYPE_STRING) &&
            (tripType!=std.persist.PRESENCE_ENTRY_TYPE_STRING) &&
            (tripType!=std.persist.FUNCTION_OBJECT_TYPE_STRING) &&
            (tripType!=std.persist.BASIC_OBJECT_TYPE_STRING))
            return true;

        return false;
    };

     /**
      @param {int} ptrId The unique name of the object that should be
      referenced by calling localCopyToPoint[index]
      @param index of the local object to perform fixup on.
      @param {object} localCopyToPoint localCopyToPoint[index] should be the new
      object pointer
      @param {array} allToFix an array.  Push the above three arguments onto that
      array (as an array).

      After rest of deserialization occurs, final step is to call
      performFinalFixups with this array as an argument.
      performPtrFinalFixups traverses array, and points
      localCopyToPoint[index] to the objects described by objPtrToFix.
      */
     function registerFixupObjectPointer(ptrId, index, localCopyToPoint, allToFix)
     {
         allToFix.push([ptrId, index,localCopyToPoint]);
     };

     /**
      locaCopyToPoint[index] should end up pointing to the object represented
      by the lookup into nameService of ptrId

      @see registerFixupObjectPointer
      @see fixSinglePtr
      */
     function fixSinglePtr (ptrId, index,localCopyToPoint,nameService)
     {
         if ((typeof(localCopyToPoint) != 'object') || (localCopyToPoint== null))
             throw new Error('Error in fixSinglePtr.  Should not have received non-obect or null ptr record.');

         var fixedObj = nameService.lookupObject(ptrId);
         if (fixedObj == nameService.DNE)
             throw new Error('Error in fixSinglePtr.  Have no record of object that you are trying to point to.');

         localCopyToPoint[index] = fixedObj;
     };

     /**
      @param {array} allToFix array.  Each element has three values. [0]
      ptrId, [1] index, [2] localCopyToPoint.

      Runs through array generated by calls to registerFixupObjectPointer,
      and individually performs fixups for each one.

      @see registerFixupObjectPointer
      @see fixSinglePtr
      */
     function performPtrFinalFixups(allToFix,nameService)
     {
         for (var s in allToFix)
             fixSinglePtr(allToFix[s][0],allToFix[s][1],allToFix[s][2],nameService);
     };

     /**
      fixReferences opens the keyName table, and returns an object whose
      subgraph is rooted at the object with id ptrId. Note: all objects the
      root object references may not be linked to correctly.  Need to call
      performPtrFinalFixups on ptrsToFix after running this function.

      @param {keyName}, Passed to the backend.  This is the entry to
      access.

      @param {int}, ptrId, Each object has a unique id.  ptrId is the
      identifier for the object that we should be fixing references for (in
      the keyName table).

      @param {array} ptrsToFix is an array that tracks all objects that we
      will need to fixup the references too.  See performFixupPtr function.

      @param nameService can be used to lookup the ids for objects that
      we've already re-read.

      @param cb callback to invoke when complete. Passed success flag (boolean)
      and, if successful, an object whose subgraph is rooted at the object with id ptrId.

      */
     function fixReferences(keyName, ptrId, ptrsToFix, nameService, cb)
     {
         readObject(
             keyName,ptrId,
             std.core.bind(finishFixReferences, undefined, keyName, ptrId, ptrsToFix, nameService, cb) // + success, object
         );
     }

     function finishFixReferences(keyName, ptrId, ptrsToFix, nameService, cb, success, unfixedObj) {
         if (!success)
         {
             cb(false);
             return;
         }

         var id = unfixedObj['mID'];
         if (id != ptrId) //throw new Error('Error: ptrId and object id must be identical');
             cb(false);

         if (nameService.lookupObject(ptrId) != nameService.DNE) // throw new Error("Error.  Called fixReferences on an object I've already visited");
             cb(false);

         var type = unfixedObj['type'];
         if (type == std.persist.FUNCTION_OBJECT_TYPE_STRING)
             restoreFunction(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.PRESENCE_OBJECT_TYPE_STRING)
             restorePresence(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.BASIC_OBJECT_TYPE_STRING)
             restoreBasicObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.VEC_TYPE_STRING)
             restoreVec3Object(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.QUAT_TYPE_STRING)
             restoreQuatObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.VISIBLE_TYPE_STRING)
             restoreVisibleObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else
             throw new Error('Error in fixReferences.  Do not have any other types in the system to restore from.');
     }

     /**
      @see fixReferences for arguments
      Returns a new visible object.
      */
     function restoreVisibleObject(keyName, visRecord,ptrId,ptrsToFix,nameService,cb)
     {
         var pToFix = [];
         restoreBasicObject(
             keyName,visRecord,ptrId,pToFix,nameService,
             std.core.bind(finishRestoreVisibleObject, undefined, keyname, visRecord, ptrId, pToFix, nameService, cb)
         );
     };
     function finishRestoreVisibleObject(keyName, visRecord,ptrId,pToFix,nameService,cb, success, toRestoreFrom) {
         if(!success) {
             cb(false);
             return;
         }

         //perform the fixups for the objects that this presence was
         //trying to point to.  (Eg. pos object, vel obj, etc.)
         performPtrFinalFixups(pToFix,nameService);

         var returner = system.createVisible(
             toRestoreFrom.sporef,
             toRestoreFrom.pos,
             toRestoreFrom.vel,
             toRestoreFrom.posTime,
             toRestoreFrom.orient,
             toRestoreFrom.orientVel,
             toRestoreFrom.orientTime,
             toRestoreFrom.pos,
             toRestoreFrom.scale,
             toRestoreFrom.mesh,
             toRestoreFrom.physics,
             toRestoreFrom.solidAngleQuery
         );

         cb(true, returner);
     }

     /**
      @see fixReferencs for arguments.
      Returns a new vec3.
      */
     function restoreVec3Object(keyName, unfixedObj,ptrId,ptrsToFix,nameService, cb)
     {
         //lkjs: may want some check here.
         var x = getValueField(unfixedObj,'x');
         var y = getValueField(unfixedObj,'y');
         var z = getValueField(unfixedObj,'z');
         var returner = new util.Vec3(x,y,z);
         nameService.insertObjectWithName(returner,ptrId);
         cb(true, returner);
     }

     /**
      @see fixReferencs for arguments.
      Returns a new quaternion.
      */
     function restoreQuatObject(keyName, unfixedObj,ptrId,ptrsToFix,nameService, cb)
     {
         var x = getValueField(unfixedObj,'x');
         var y = getValueField(unfixedObj,'y');
         var z = getValueField(unfixedObj,'z');
         var w = getValueField(unfixedObj,'w');

         var returner = new util.Quaternion(x,y,z,w);
         nameService.insertObjectWithName(returner,ptrId);
         cb(true, returner);
     }

     /**
      @param unfixedObj Is an object that is read in directly from the
      backend.  It has three types of fields: 1) triplets, 2) mID (obj
      id), 3) type (obj type).

      @param Field name that we're looking for in one of the triplets.

      @return returns the value of the triplet associated with
      filedName

      @throw Throws an error if fieldName does not exist as a field in
      any of unfixedObj's triplets.

      This function runs through all the triplets in unfixedObj, and
      returns the value of the triplet that matches the field.
      */
     function getValueField(unfixedObj,fieldName)
     {
         for (var s in unfixedObj)
         {
             if ((s == 'mID') || (s == 'type'))
                 continue;

             var propValTypeTriple = unfixedObj[s];

             var tripFieldName = tripletGetIndexName(unfixedObj[s]);
             if (tripFieldName == fieldName)
                 return tripletGetValue(propValTypeTriple);
         }
         throw new Error('Error in getValueField.  Have no field named: '+ fieldName);
     }

     /**
      For keyName,ptrId,ptrsToFix, and nameService, @see fixReferences.

      unfixedPres has all the data that you would get from a call to
      getAllData on a presence.

      */
     function restorePresence(keyName,unfixedPres,ptrId,ptrsToFix,nameService, cb)
     {
         var pToFix = [];
         restoreBasicObject(
             keyName,unfixedPres,ptrId,pToFix,nameService,
             std.core.bind(finishRestorePresence, undefined, keyName, unfixedPres, ptrId, pToFix, nameService, cb) // + success, obj
         );
     }
     function finishRestorePresence(keyName,unfixedPres,ptrId,pToFix,nameService, cb, success, toRestoreFrom) {
         if(!success) {
             cb(false);
             return;
         }

         //perform the fixups for the objects that this presence was
         //trying to point to.  (Eg. pos object, vel obj, etc.)
         performPtrFinalFixups(pToFix,nameService);

         for (var s in system.presences)
         {
             if (system.presences[s].toString() == toRestoreFrom.sporef)
             {
                 cb(true,system.presences[s]);
                 return;
             }
         }

         //tells the system that we have begun trying to restore this
         //presence, and not to continue with later stages of
         //restoration (fixing looped object pointers) until the
         //system has connected this presence.
         registerPresenceStillRestoring(ptrId);

         var onConnectCB = afterRestored(ptrId,nameService,cb);
         system.restorePresence(
             toRestoreFrom.sporef,
             toRestoreFrom.pos,
             toRestoreFrom.vel,
             toRestoreFrom.posTime,
             toRestoreFrom.orient,
             toRestoreFrom.orientVel,
             toRestoreFrom.orientTime,
             toRestoreFrom.mesh,
             toRestoreFrom.scale,
             toRestoreFrom.isCleared,
             toRestoreFrom.contextId,
             toRestoreFrom.isConnected,
             onConnectCB,
             toRestoreFrom.isSuspended,
             toRestoreFrom.suspendedVelocity,
             toRestoreFrom.suspendedOrientationVelocity,
             toRestoreFrom.solidAngleQuery
         );
     };

     /**
      For keyName,ptrId,ptrsToFix, and nameService, @see fixReferences.

      unfixedFunc right now just has one field: 'funcField' with the
      text of the function that we're creating.
      */
     function restoreFunction(keyName,unfixedFunc,ptrId,ptrsToFix,nameService, cb)
     {
         //FIXME: lkjs;  GROSS!
         var funcTriple = unfixedFunc[0];

         var index = tripletGetIndexName(funcTriple);
         if (index != 'funcField')
             throw new Error('Error restoring function.  Restoring object does not have funcField.');

         var funcAsString = tripletGetValue(funcTriple);
         funcAsString = '(' + funcAsString + ')';

         var returner = null;
         var success = true;
         try
         {
             returner = system.eval(funcAsString);
         }
         catch (excep)
         {
             system.print('ERROR: Error in restoreFunction.  Trying to restore a function with faulty syntax. Key: ' + keyName + '\n');
             returner = function(){};
             success = false;
         }
         nameService.insertObjectWithName(returner,ptrId);
         cb(success, returner);
     }

     /**
      For keyName, ptrId,ptrsToFix, and nameService, @see fixReferences.

      @param unfixedObj is the object that we get back from reading
      from reading from backend.  It is a basic object (not a
      function, presence, system obj, etc.).  This function runs
      through all of its fields and registers them to be fixed up.

      */
     function restoreBasicObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb)
     {
         var returner = { };
         nameService.insertObjectWithName(returner,ptrId);
         //run through all the fields in unfixedObj.  If the field is a
         //value type, point returner to the new field right away.  If the
         //field is an object type and we have a copy of that object, then
         //point returner to that new object right away.  If the field is
         //an object type and we do not have a copy of that object, then
         //register returner to be fixed-up with the new pointer later.

         var unfinished_fields = 0;
         var did_callback = false;
         var finish_field_cb = function(success, val) {
             if (!success && !did_callback) {
                 did_callback = true;
                 cb(false);
                 return;
             }
             unfinished_fields -= 1;
             if (unfinished_fields == 0) {
                 did_callback = true;
                 cb(true, returner);
             }
         };
         for (var s in unfixedObj)
         {
             if ((s == 'mID') || (s == 'type'))
                 continue;

             var index = tripletGetIndexName(unfixedObj[s]);

             //sets to value type
             if (tripletIsValueType(unfixedObj[s]))
                 returner[index] = tripletGetValue(unfixedObj[s]);
             else
             {
                 if ((tripletGetType(unfixedObj[s])) == 'null')
                     returner[index] = null;
                 else
                 {
                     var ptrIdInner  = tripletGetValue(unfixedObj[s]);
                     var ptrObj = nameService.lookupObject(ptrIdInner);
                     if (ptrObj != nameService.DNE)
                     {
                         //already have the object.  just link to it.
                         returner[index] = ptrObj;
                     }
                     else
                     {
                         //will have to register this pointer to be fixed up
                         registerFixupObjectPointer( ptrIdInner ,index,returner,ptrsToFix);
                         unfinished_fields += 1;
                         fixReferences(keyName,ptrIdInner,ptrsToFix,nameService, std.core.bind(finish_field_cb, undefined));
                     }
                 }
             }
         }

         // Special case for empty objects
         if (unfinished_fields == 0)
             cb(true, returner);
     };

     /**
      Returns true if we're in the middle of a restore operation.
      Otherwise, returns false.
      */
     std.persist.inRestore = function()
     {
         return mRestoring;
     };

     /**
      @see std.persist.restoreFromAndGetNamesAsync
      */
     std.persist.restoreFromAsync = function (keyName,cb)
     {
         return std.persist.restoreFromAndGetNamesAsync(keyName,0,cb);
     };

     /**
      This function should be used if the object graph that you are
      trying to restore has presences in it, and you need to wait for
      the system to actually connect these presences.

      @param cb Takes in three parameters, first is restored obj graph
      (if pres failure, all presences become null objs.), second
      boolean for success (ie true if eveything restored
      appropriately, and space allowed new presences to reconnect,
      false otherwise), the third is the nameService that we used.
      */
     std.persist.restoreFromAndGetNamesAsync = function (keyName,id,cb)
     {
         if (std.persist.inRestore())
             throw new Error('Error, cannot request additional restores when in middle of current restore.  Check back later.');
         mRestoring = true;

         var nameService = new std.persist.NameService();
         var ptrsToFix = [];

         // Setup a timeout in case we fail to get all presences reconnected
         var restoreCheckback = function() {
             cb(false);
         };
         var tout = system.timeout(60,restoreCheckback);

         fixReferences(
             keyName, id,ptrsToFix,nameService,
             std.core.bind(finishRestoreFromAndGetNamesAsync, undefined, keyName, id, cb, ptrsToFix, nameService, tout) // + success, obj
         );
     };

     var finishRestoreFromAndGetNamesAsync = function (keyName,id,cb, ptrsToFix, nameService, timeout, success, returner) {
         // Clear timeout since we've either succeeded or permanently failed
         timeout.clear();

         if (!success) {
             mRestoring = false;
             cb(false);
             return;
         }
         if (Object.keys(allPresStillRest).length != 0) {
             system.print("Error: Shouldn't get finishRestoreFromAndGetNamesAsync callback until all presences are restored.\n");
             mRestoring = false;
             cb(false);
             return;
         }

         // Success
         performPtrFinalFixups(ptrsToFix,nameService);
         mRestoring = false;
         cb(true,returner,nameService);
     };

 })();

if (typeof(std.persist) === 'undefined')
    throw new Error('Error.  Do not import this file directly.  Only import it from persistService.em');

(function()
 {

     /**
      Each element of this array contains the unique id given to the
      presence object when it was being persisted.  And each element
      correpsonds to a presence that is trying to be restored in the
      world.
      */
     var allPresStillRest = {};

     var mRestoring = false;

     function registerPresenceStillRestoring(presObjID)
     {
         allPresStillRest[presObjID] = presObjID;
     }

     /**
      Each restored presence has an onConnected callback.  The
      onConnected callback should be generated from this afterRestored
      function.  All that the callback does is update the nameService
      that we're using with the new presence object and removes this
      presence from the list of presences that we are restoring that
      are still waiting to be connected (in allPresStillRest).

      Second stage of restoration (fixing up pointers to other
      objects) waits until all presences have been connected (polls
      allPresStillRest to see if have zero length).

      @param {int} presObjID, unique name that was given to presence
      before restore.  (ie name that goes into nameService.)

      @param nameService nameService used during restoration.
      */
     function afterRestored(presObjID,nameService,cb)
     {
         var returner = function()
         {
             //insert the presence into nameService;
             nameService.insertObjectWithName(system.self,presObjID);
             delete allPresStillRest[presObjID];
             if (Object.keys(allPresStillRest).length == 0)
                 cb(true, null); // Not sure about this being null....
        };
         return returner;
     }

     function checkIsTriplet(toCheck)
     {
         if ((typeof(toCheck) !== 'object') || (!('length' in toCheck)) || (toCheck.length != 3))
             return false;

         return true;
     }

     function tripletGetIndexName(triplet)
     {
         if (!checkIsTriplet(triplet))
         {
             system.prettyprint(triplet);
             throw new Error('Error in tripletGetIndexName.  Requires triplet to be passed in');
         }

         return triplet[0];
     }

     function tripletGetValue(triplet)
     {
         if (!checkIsTriplet(triplet))
             throw new Error('Error in tripletGetValue.  Requires triplet to be passed in');

         var type = tripletGetType(triplet);
         if (type == 'number')
             return parseFloat(triplet[1]);
         if (type == 'string')
             return triplet[1];
         if (type == 'boolean')
             return (triplet[1] == 'true');

         return triplet[1];
     }

     function tripletGetType(triplet)
     {
         if (!checkIsTriplet(triplet))
             throw new Error('Error in tripletGetType.  Requires triplet to be passed in');
         return triplet[2];
     }

    /**
     @param {array} triplet Array containing three values.  Indices of
     array follow:
       0 : index
       1 : value to set to/object pointer/'null'
       2 : type record

     @return {boolean} Returns true if the value in this object is a
     value type
     */
    function tripletIsValueType (triplet)
    {
        if (! checkIsTriplet(triplet))
            throw new Error('Error in checkTripletIsValueType.  Requires triplet to be passed in');

        var tripType = tripletGetType(triplet);

        if ((tripType != 'object') && (tripType != 'function') &&
            (tripType!=std.persist.SYSTEM_TYPE_STRING) &&
            (tripType!=std.persist.PRESENCE_OBJECT_TYPE_STRING) &&
            (tripType!=std.persist.VISIBLE_TYPE_STRING) &&
            (tripType!=std.persist.TIMER_TYPE_STRING) &&
            (tripType!=std.persist.PRESENCE_ENTRY_TYPE_STRING) &&
            (tripType!=std.persist.FUNCTION_OBJECT_TYPE_STRING) &&
            (tripType!=std.persist.BASIC_OBJECT_TYPE_STRING))
            return true;

        return false;
    };

     /**
      @param {int} ptrId The unique name of the object that should be
      referenced by calling localCopyToPoint[index]
      @param index of the local object to perform fixup on.
      @param {object} localCopyToPoint localCopyToPoint[index] should be the new
      object pointer
      @param {array} allToFix an array.  Push the above three arguments onto that
      array (as an array).

      After rest of deserialization occurs, final step is to call
      performFinalFixups with this array as an argument.
      performPtrFinalFixups traverses array, and points
      localCopyToPoint[index] to the objects described by objPtrToFix.
      */
     function registerFixupObjectPointer(ptrId, index, localCopyToPoint, allToFix)
     {
         allToFix.push([ptrId, index,localCopyToPoint]);
     };

     /**
      locaCopyToPoint[index] should end up pointing to the object represented
      by the lookup into nameService of ptrId

      @see registerFixupObjectPointer
      @see fixSinglePtr
      */
     function fixSinglePtr (ptrId, index,localCopyToPoint,nameService)
     {
         if ((typeof(localCopyToPoint) != 'object') || (localCopyToPoint== null))
             throw new Error('Error in fixSinglePtr.  Should not have received non-obect or null ptr record.');

         var fixedObj = nameService.lookupObject(ptrId);
         if (fixedObj == nameService.DNE)
             throw new Error('Error in fixSinglePtr.  Have no record of object that you are trying to point to.');

         localCopyToPoint[index] = fixedObj;
     };

     /**
      @param {array} allToFix array.  Each element has three values. [0]
      ptrId, [1] index, [2] localCopyToPoint.

      Runs through array generated by calls to registerFixupObjectPointer,
      and individually performs fixups for each one.

      @see registerFixupObjectPointer
      @see fixSinglePtr
      */
     function performPtrFinalFixups(allToFix,nameService)
     {
         for (var s in allToFix)
             fixSinglePtr(allToFix[s][0],allToFix[s][1],allToFix[s][2],nameService);
     };

     /**
      fixReferences opens the keyName table, and returns an object whose
      subgraph is rooted at the object with id ptrId. Note: all objects the
      root object references may not be linked to correctly.  Need to call
      performPtrFinalFixups on ptrsToFix after running this function.

      @param {keyName}, Passed to the backend.  This is the entry to
      access.

      @param {int}, ptrId, Each object has a unique id.  ptrId is the
      identifier for the object that we should be fixing references for (in
      the keyName table).

      @param {array} ptrsToFix is an array that tracks all objects that we
      will need to fixup the references too.  See performFixupPtr function.

      @param nameService can be used to lookup the ids for objects that
      we've already re-read.

      @param cb callback to invoke when complete. Passed success flag (boolean)
      and, if successful, an object whose subgraph is rooted at the object with id ptrId.

      */
     function fixReferences(keyName, ptrId, ptrsToFix, nameService, cb)
     {
         readObject(
             keyName,ptrId,
             std.core.bind(finishFixReferences, undefined, keyName, ptrId, ptrsToFix, nameService, cb) // + success, object
         );
     }

     function finishFixReferences(keyName, ptrId, ptrsToFix, nameService, cb, success, unfixedObj) {
         if (!success)
         {
             cb(false);
             return;
         }

         var id = unfixedObj['mID'];
         if (id != ptrId) //throw new Error('Error: ptrId and object id must be identical');
             cb(false);

         if (nameService.lookupObject(ptrId) != nameService.DNE) // throw new Error("Error.  Called fixReferences on an object I've already visited");
             cb(false);

         var type = unfixedObj['type'];
         if (type == std.persist.FUNCTION_OBJECT_TYPE_STRING)
             restoreFunction(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.PRESENCE_OBJECT_TYPE_STRING)
             restorePresence(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.BASIC_OBJECT_TYPE_STRING)
             restoreBasicObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.VEC_TYPE_STRING)
             restoreVec3Object(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.QUAT_TYPE_STRING)
             restoreQuatObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else if (type == std.persist.VISIBLE_TYPE_STRING)
             restoreVisibleObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb);
         else
             throw new Error('Error in fixReferences.  Do not have any other types in the system to restore from.');
     }

     /**
      @see fixReferences for arguments
      Returns a new visible object.
      */
     function restoreVisibleObject(keyName, visRecord,ptrId,ptrsToFix,nameService,cb)
     {
         var pToFix = [];
         restoreBasicObject(
             keyName,visRecord,ptrId,pToFix,nameService,
             std.core.bind(finishRestoreVisibleObject, undefined, keyname, visRecord, ptrId, pToFix, nameService, cb)
         );
     };
     function finishRestoreVisibleObject(keyName, visRecord,ptrId,pToFix,nameService,cb, success, toRestoreFrom) {
         if(!success) {
             cb(false);
             return;
         }

         //perform the fixups for the objects that this presence was
         //trying to point to.  (Eg. pos object, vel obj, etc.)
         performPtrFinalFixups(pToFix,nameService);

         var returner = system.createVisible(
             toRestoreFrom.sporef,
             toRestoreFrom.pos,
             toRestoreFrom.vel,
             toRestoreFrom.posTime,
             toRestoreFrom.orient,
             toRestoreFrom.orientVel,
             toRestoreFrom.orientTime,
             toRestoreFrom.pos,
             toRestoreFrom.scale,
             toRestoreFrom.mesh,
             toRestoreFrom.physics,
             toRestoreFrom.solidAngleQuery
         );

         cb(true, returner);
     }

     /**
      @see fixReferencs for arguments.
      Returns a new vec3.
      */
     function restoreVec3Object(keyName, unfixedObj,ptrId,ptrsToFix,nameService, cb)
     {
         //lkjs: may want some check here.
         var x = getValueField(unfixedObj,'x');
         var y = getValueField(unfixedObj,'y');
         var z = getValueField(unfixedObj,'z');
         var returner = new util.Vec3(x,y,z);
         nameService.insertObjectWithName(returner,ptrId);
         cb(true, returner);
     }

     /**
      @see fixReferencs for arguments.
      Returns a new quaternion.
      */
     function restoreQuatObject(keyName, unfixedObj,ptrId,ptrsToFix,nameService, cb)
     {
         var x = getValueField(unfixedObj,'x');
         var y = getValueField(unfixedObj,'y');
         var z = getValueField(unfixedObj,'z');
         var w = getValueField(unfixedObj,'w');

         var returner = new util.Quaternion(x,y,z,w);
         nameService.insertObjectWithName(returner,ptrId);
         cb(true, returner);
     }

     /**
      @param unfixedObj Is an object that is read in directly from the
      backend.  It has three types of fields: 1) triplets, 2) mID (obj
      id), 3) type (obj type).

      @param Field name that we're looking for in one of the triplets.

      @return returns the value of the triplet associated with
      filedName

      @throw Throws an error if fieldName does not exist as a field in
      any of unfixedObj's triplets.

      This function runs through all the triplets in unfixedObj, and
      returns the value of the triplet that matches the field.
      */
     function getValueField(unfixedObj,fieldName)
     {
         for (var s in unfixedObj)
         {
             if ((s == 'mID') || (s == 'type'))
                 continue;

             var propValTypeTriple = unfixedObj[s];

             var tripFieldName = tripletGetIndexName(unfixedObj[s]);
             if (tripFieldName == fieldName)
                 return tripletGetValue(propValTypeTriple);
         }
         throw new Error('Error in getValueField.  Have no field named: '+ fieldName);
     }

     /**
      For keyName,ptrId,ptrsToFix, and nameService, @see fixReferences.

      unfixedPres has all the data that you would get from a call to
      getAllData on a presence.

      */
     function restorePresence(keyName,unfixedPres,ptrId,ptrsToFix,nameService, cb)
     {
         var pToFix = [];
         restoreBasicObject(
             keyName,unfixedPres,ptrId,pToFix,nameService,
             std.core.bind(finishRestorePresence, undefined, keyName, unfixedPres, ptrId, pToFix, nameService, cb) // + success, obj
         );
     }
     function finishRestorePresence(keyName,unfixedPres,ptrId,pToFix,nameService, cb, success, toRestoreFrom) {
         if(!success) {
             cb(false);
             return;
         }

         //perform the fixups for the objects that this presence was
         //trying to point to.  (Eg. pos object, vel obj, etc.)
         performPtrFinalFixups(pToFix,nameService);

         for (var s in system.presences)
         {
             if (system.presences[s].toString() == toRestoreFrom.sporef)
             {
                 cb(true,system.presences[s]);
                 return;
             }
         }

         //tells the system that we have begun trying to restore this
         //presence, and not to continue with later stages of
         //restoration (fixing looped object pointers) until the
         //system has connected this presence.
         registerPresenceStillRestoring(ptrId);

         var onConnectCB = afterRestored(ptrId,nameService,cb);
         system.restorePresence(
             toRestoreFrom.sporef,
             toRestoreFrom.pos,
             toRestoreFrom.vel,
             toRestoreFrom.posTime,
             toRestoreFrom.orient,
             toRestoreFrom.orientVel,
             toRestoreFrom.orientTime,
             toRestoreFrom.mesh,
             toRestoreFrom.scale,
             toRestoreFrom.isCleared,
             toRestoreFrom.contextId,
             toRestoreFrom.isConnected,
             onConnectCB,
             toRestoreFrom.isSuspended,
             toRestoreFrom.suspendedVelocity,
             toRestoreFrom.suspendedOrientationVelocity,
             toRestoreFrom.solidAngleQuery
         );
     };

     /**
      For keyName,ptrId,ptrsToFix, and nameService, @see fixReferences.

      unfixedFunc right now just has one field: 'funcField' with the
      text of the function that we're creating.
      */
     function restoreFunction(keyName,unfixedFunc,ptrId,ptrsToFix,nameService, cb)
     {
         //FIXME: lkjs;  GROSS!
         var funcTriple = unfixedFunc[0];

         var index = tripletGetIndexName(funcTriple);
         if (index != 'funcField')
             throw new Error('Error restoring function.  Restoring object does not have funcField.');

         var funcAsString = tripletGetValue(funcTriple);

         var returner = null;
         var success = true;
         try
         {
             returner = system.eval(funcAsString);
         }
         catch (excep)
         {
             system.print('ERROR: Error in restoreFunction.  Trying to restore a function with faulty syntax. Key: ' + keyName + '\n');
             returner = function(){};
             success = false;
         }
         nameService.insertObjectWithName(returner,ptrId);
         cb(success, returner);
     }

     /**
      For keyName, ptrId,ptrsToFix, and nameService, @see fixReferences.

      @param unfixedObj is the object that we get back from reading
      from reading from backend.  It is a basic object (not a
      function, presence, system obj, etc.).  This function runs
      through all of its fields and registers them to be fixed up.

      */
     function restoreBasicObject(keyName,unfixedObj,ptrId,ptrsToFix,nameService,cb)
     {
         var returner = { };
         nameService.insertObjectWithName(returner,ptrId);
         //run through all the fields in unfixedObj.  If the field is a
         //value type, point returner to the new field right away.  If the
         //field is an object type and we have a copy of that object, then
         //point returner to that new object right away.  If the field is
         //an object type and we do not have a copy of that object, then
         //register returner to be fixed-up with the new pointer later.

         var unfinished_fields = 0;
         var did_callback = false;
         var finish_field_cb = function(success, val) {
             if (!success && !did_callback) {
                 did_callback = true;
                 cb(false);
                 return;
             }
             unfinished_fields -= 1;
             if (unfinished_fields == 0) {
                 did_callback = true;
                 cb(true, returner);
             }
         };
         for (var s in unfixedObj)
         {
             if ((s == 'mID') || (s == 'type'))
                 continue;

             var index = tripletGetIndexName(unfixedObj[s]);

             //sets to value type
             if (tripletIsValueType(unfixedObj[s]))
                 returner[index] = tripletGetValue(unfixedObj[s]);
             else
             {
                 if ((tripletGetType(unfixedObj[s])) == 'null')
                     returner[index] = null;
                 else
                 {
                     var ptrIdInner  = tripletGetValue(unfixedObj[s]);
                     var ptrObj = nameService.lookupObject(ptrIdInner);
                     if (ptrObj != nameService.DNE)
                     {
                         //already have the object.  just link to it.
                         returner[index] = ptrObj;
                     }
                     else
                     {
                         //will have to register this pointer to be fixed up
                         registerFixupObjectPointer( ptrIdInner ,index,returner,ptrsToFix);
                         unfinished_fields += 1;
                         fixReferences(keyName,ptrIdInner,ptrsToFix,nameService, std.core.bind(finish_field_cb, undefined));
                     }
                 }
             }
         }

         // Special case for empty objects
         if (unfinished_fields == 0)
             cb(true, returner);
     };

     /**
      Returns true if we're in the middle of a restore operation.
      Otherwise, returns false.
      */
     std.persist.inRestore = function()
     {
         return mRestoring;
     };

     /**
      @see std.persist.restoreFromAndGetNamesAsync
      */
     std.persist.restoreFromAsync = function (keyName,cb)
     {
         return std.persist.restoreFromAndGetNamesAsync(keyName,0,cb);
     };

     /**
      This function should be used if the object graph that you are
      trying to restore has presences in it, and you need to wait for
      the system to actually connect these presences.

      @param cb Takes in three parameters, first is restored obj graph
      (if pres failure, all presences become null objs.), second
      boolean for success (ie true if eveything restored
      appropriately, and space allowed new presences to reconnect,
      false otherwise), the third is the nameService that we used.
      */
     std.persist.restoreFromAndGetNamesAsync = function (keyName,id,cb)
     {
         if (std.persist.inRestore())
             throw new Error('Error, cannot request additional restores when in middle of current restore.  Check back later.');
         mRestoring = true;

         var nameService = new std.persist.NameService();
         var ptrsToFix = [];

         // Setup a timeout in case we fail to get all presences reconnected
         var restoreCheckback = function() {
             cb(false);
         };
         var tout = system.timeout(60,restoreCheckback);

         fixReferences(
             keyName, id,ptrsToFix,nameService,
             std.core.bind(finishRestoreFromAndGetNamesAsync, undefined, keyName, id, cb, ptrsToFix, nameService, tout) // + success, obj
         );
     };

     var finishRestoreFromAndGetNamesAsync = function (keyName,id,cb, ptrsToFix, nameService, timeout, success, returner) {
         // Clear timeout since we've either succeeded or permanently failed
         timeout.clear();

         if (!success) {
             mRestoring = false;
             cb(false);
             return;
         }
         if (Object.keys(allPresStillRest).length != 0) {
             system.print("Error: Shouldn't get finishRestoreFromAndGetNamesAsync callback until all presences are restored.\n");
             mRestoring = false;
             cb(false);
             return;
         }

         // Success
         performPtrFinalFixups(ptrsToFix,nameService);
         mRestoring = false;
         cb(true,returner,nameService);
     };

 })();


tweaking our way out of repo-wasting screwup

#!/usr/bin/make -f

# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
export DH_OPTIONS=-v

%:
       dh  $@@

override_dh_auto_configure:
       dh_auto_configure -Scmake -- \
               -DCMAKE_INSTALL_PREFIX="@(CMAKE_INSTALL_PREFIX)" \
               -DCMAKE_PREFIX_PATH="@(CMAKE_INSTALL_PREFIX)" \
               -DCATKIN_PACKAGE_PREFIX="@(CATKIN_PACKAGE_PREFIX)" \
               -DCATKIN=YES
       dh_auto_configure -Spython_distutils

override_dh_auto_install:
       dh_auto_install -Scmake
       dh_auto_install -Spython_distutils -- --prefix="@(CMAKE_INSTALL_PREFIX)"

override_dh_auto_build:
       dh_auto_build -Scmake
       dh_auto_build -Spython_distutils

#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
export DH_OPTIONS=-v

# include $(catkin_DIR)/debian.rules

%:
       dh  $@@

override_dh_auto_configure:
       dh_auto_configure -Scmake -- \
               -DCMAKE_INSTALL_PREFIX="@(CMAKE_INSTALL_PREFIX)" \
               -DCMAKE_PREFIX_PATH="@(CMAKE_PREFIX_PATH)" \
               -DCATKIN_PACKAGE_PREFIX="@(CATKIN_PACKAGE_PREFIX)" \
               -DCATKIN=YES

       dh_auto_configure -Spython_distutils

override_dh_auto_install:
       dh_auto_install -Scmake
       dh_auto_install -Spython_distutils -- --prefix="@(CMAKE_INSTALL_PREFIX)"

override_dh_auto_build:
       dh_auto_build -Scmake
       dh_auto_build -Spython_distutils


Can now pass undefined's through gui calls.  Previously got error because tried to call .toString on it (which throws an error).

/*  Sirikata
 *  graphics.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('std/escape.em');

if (typeof(std) === "undefined") std = {};
if (typeof(std.graphics) === "undefined") std.graphics = {};

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The GUI class wraps the underlying GUI Invokable
     *  objects. These present 2D user interface widgets to the user,
     *  which are coded as HTML + Javascript pages.
     *
     *  The callback is passed this GUI as a parameter.
     */
    std.graphics.GUI = function(name, me, onready) {
        this._name = name;
        this._gui = me;
        if (onready)
            this.bind('__ready', std.core.bind(onready, undefined, this));
    };

    var dispatchBindCallback = function(cb) {
        // Any additional arguments after cb are arguments. They're JSON encoded, so we need to decode before passing them along.
        var args = [];
        for(var i = 1; i < arguments.length; i++) {
            var parsed = JSON.parse(arguments[i]);
            args.push(parsed);
        }

        cb.apply(undefined, args);
    };

    /** Bind a listener for events from this GUI. */
    std.graphics.GUI.prototype.bind = function(type, cb) {
        this._gui.invoke("bind", this._name + '-' + type, std.core.bind(dispatchBindCallback, undefined, cb));
    };

    /** Evaluate the Javascript string inside the GUI context. */
    std.graphics.GUI.prototype.guiEval = function(js) {
        this._gui.invoke("eval", js);
    };

    var getGUIJSValue = function(arg) {
        if (typeof(arg) === 'string')
            return Escape.escapeString(arg, '"');
        else if (typeof(arg) === 'undefined')
             return undefined;
        else if ((typeof(arg) === 'object' && arg === null) ||
                 typeof(arg) === 'number' ||
                 typeof(arg) === 'boolean')
            return arg.toString();
        else if (typeof(arg) === 'object' && typeof(arg.__var) === 'string' )
            return arg.__var; // Variables, see GUI.variable
        else {
            // Non-trivial type. Try to JSONify it.
            try {
                var arg_json = JSON.stringify(arg);
                // And wrap in decoding call
                return 'JSON.parse(' + Escape.escapeString(arg_json) + ')';
            } catch (x) {
                throw new TypeError("Invalid object type passed to GUI.call. Must be basic type (undefined, null, boolean, number, string) or JSON-encodable.");
            }
        }
    };

    /** Create an object which can be used to specify a variable name
     *  to GUI.call and GUI.set. Since strings are converted to string
     *  literals, it isn't possible to specify variable names in these
     *  calls without this method.
     *
     *  @param {string} name the name of the variable
     *  @returns {object} a placeholder object which gets converted to
     *  the variable name when passed to GUI.call or GUI.set.
     */
    std.graphics.GUI.prototype.variable = function(name) {
        // Just a special object, see getGUIJSValue for how it is used.
        return {
            '__var' : name
        };
    };

    /** Call a method in the GUI context. This is just a convenience
     *  wrapper around eval which will build the string to eval
     *  automatically from the method arguments.
     *
     *  Example:
     *   var x = 7;
     *   var st = 'hello "Bob"';
     *   gui.call('myfunc', x, st);
     *  is equivalent to
     *   gui.guiEval( "myfunc(7, 'hello \"Bob\"');" );
     */
    std.graphics.GUI.prototype.call = function() {
        if (arguments.length < 1) return;
        var methodname = arguments[0];

        var ev_str = methodname + '(';

        for(var i = 1; i < arguments.length; i++) {
            if (i > 1) ev_str += ', ';

            var arg = arguments[i];
            ev_str += getGUIJSValue(arg);
        }

        ev_str += ')';

        this.guiEval(ev_str);
    };

    /** Set the value of a variable in the GUI context. This is just a
     *  convenience wrapper around eval which will build the string to
     *  eval automatically from the arguments.
     *
     *  Example:
     *   gui.set('myvar', 17)
     *  is equivalent to
     *   gui.eval('var myvar = 17;');
     *
     */
    std.graphics.GUI.prototype.set = function(varname, value) {
        var ev_str = varname + ' = ' + getGUIJSValue(value) + ';';
        this.guiEval(ev_str);
    };

    /** Hides the GUI window. */
    std.graphics.GUI.prototype.hide = function() {
        this._gui.invoke("hide");
    };

    /** Shows the GUI window. */
    std.graphics.GUI.prototype.show = function() {
        this._gui.invoke("show");
    };

    /** Shows the GUI window. */
    std.graphics.GUI.prototype.focus = function() {
        this._gui.invoke("focus");
    };

    /** Bind a listener for exception events. Listener should have the form fn(message, file, linenum). */
    std.graphics.GUI.prototype.onException = function(cb) {
        this._gui.invoke("onException", cb);
    };

    /** Get the current URL. Should only be used on browsers, not regular GUIs, since the GUI URL won't be meaningful. */
    std.graphics.GUI.prototype.url = function() {
        return this._gui.invoke("url");
    };

})();

/*  Sirikata
 *  graphics.em
 *
 *  Copyright (c) 2011, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require('std/escape.em');

if (typeof(std) === "undefined") std = {};
if (typeof(std.graphics) === "undefined") std.graphics = {};

(
function() {

    var ns = std.graphics;

    /** @namespace
     *  The GUI class wraps the underlying GUI Invokable
     *  objects. These present 2D user interface widgets to the user,
     *  which are coded as HTML + Javascript pages.
     *
     *  The callback is passed this GUI as a parameter.
     */
    std.graphics.GUI = function(name, me, onready) {
        this._name = name;
        this._gui = me;
        if (onready)
            this.bind('__ready', std.core.bind(onready, undefined, this));
    };

    var dispatchBindCallback = function(cb) {
        // Any additional arguments after cb are arguments. They're JSON encoded, so we need to decode before passing them along.
        var args = [];
        for(var i = 1; i < arguments.length; i++) {
            var parsed = JSON.parse(arguments[i]);
            args.push(parsed);
        }

        cb.apply(undefined, args);
    };

    /** Bind a listener for events from this GUI. */
    std.graphics.GUI.prototype.bind = function(type, cb) {
        this._gui.invoke("bind", this._name + '-' + type, std.core.bind(dispatchBindCallback, undefined, cb));
    };

    /** Evaluate the Javascript string inside the GUI context. */
    std.graphics.GUI.prototype.guiEval = function(js) {
        this._gui.invoke("eval", js);
    };

    var getGUIJSValue = function(arg) {
        if (typeof(arg) === 'string')
            return Escape.escapeString(arg, '"');
        else if (typeof(arg) === 'undefined' ||
                 (typeof(arg) === 'object' && arg === null) ||
                 typeof(arg) === 'number' ||
                 typeof(arg) === 'boolean')
            return arg.toString();
        else if (typeof(arg) === 'object' && typeof(arg.__var) === 'string' )
            return arg.__var; // Variables, see GUI.variable
        else {
            // Non-trivial type. Try to JSONify it.
            try {
                var arg_json = JSON.stringify(arg);
                // And wrap in decoding call
                return 'JSON.parse(' + Escape.escapeString(arg_json) + ')';
            } catch (x) {
                throw new TypeError("Invalid object type passed to GUI.call. Must be basic type (undefined, null, boolean, number, string) or JSON-encodable.");
            }
        }
    };

    /** Create an object which can be used to specify a variable name
     *  to GUI.call and GUI.set. Since strings are converted to string
     *  literals, it isn't possible to specify variable names in these
     *  calls without this method.
     *
     *  @param {string} name the name of the variable
     *  @returns {object} a placeholder object which gets converted to
     *  the variable name when passed to GUI.call or GUI.set.
     */
    std.graphics.GUI.prototype.variable = function(name) {
        // Just a special object, see getGUIJSValue for how it is used.
        return {
            '__var' : name
        };
    };

    /** Call a method in the GUI context. This is just a convenience
     *  wrapper around eval which will build the string to eval
     *  automatically from the method arguments.
     *
     *  Example:
     *   var x = 7;
     *   var st = 'hello "Bob"';
     *   gui.call('myfunc', x, st);
     *  is equivalent to
     *   gui.guiEval( "myfunc(7, 'hello \"Bob\"');" );
     */
    std.graphics.GUI.prototype.call = function() {
        if (arguments.length < 1) return;
        var methodname = arguments[0];

        var ev_str = methodname + '(';

        for(var i = 1; i < arguments.length; i++) {
            if (i > 1) ev_str += ', ';

            var arg = arguments[i];
            ev_str += getGUIJSValue(arg);
        }

        ev_str += ')';

        this.guiEval(ev_str);
    };

    /** Set the value of a variable in the GUI context. This is just a
     *  convenience wrapper around eval which will build the string to
     *  eval automatically from the arguments.
     *
     *  Example:
     *   gui.set('myvar', 17)
     *  is equivalent to
     *   gui.eval('var myvar = 17;');
     *
     */
    std.graphics.GUI.prototype.set = function(varname, value) {
        var ev_str = varname + ' = ' + getGUIJSValue(value) + ';';
        this.guiEval(ev_str);
    };

    /** Hides the GUI window. */
    std.graphics.GUI.prototype.hide = function() {
        this._gui.invoke("hide");
    };

    /** Shows the GUI window. */
    std.graphics.GUI.prototype.show = function() {
        this._gui.invoke("show");
    };

    /** Shows the GUI window. */
    std.graphics.GUI.prototype.focus = function() {
        this._gui.invoke("focus");
    };

    /** Bind a listener for exception events. Listener should have the form fn(message, file, linenum). */
    std.graphics.GUI.prototype.onException = function(cb) {
        this._gui.invoke("onException", cb);
    };

    /** Get the current URL. Should only be used on browsers, not regular GUIs, since the GUI URL won't be meaningful. */
    std.graphics.GUI.prototype.url = function() {
        return this._gui.invoke("url");
    };

})();