Theme the LinkInfo label that is displayed in Browse at the bottom left

Set the color of the label and the background of it's parent the
overlay. Labels don't create their own window to render themselves
into. Instead, they draw themselves directly onto their parents
window, so we have to set the background-color of the parent in order
to set the labels' background color [1].

The patch does adjust the Browse entry names to be consistent.

[1] http://developer.gnome.org/gtk-faq/stable/x810.html

Signed-off-by: Simon Schampijer <088e16a1019277b15d58faf0541e11910eb756f6@schampijer.de>

${
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 scaling == "100":
    xo = True
    line_width = 2.0        # 2.25px, rounded down
    thick_line_width = 3.5  # 3.5
    subcell_size = 15
    icon_base = 11
    bullet_size = 9.5
    font_height = 24
    default_padding = 6
    toolbutton_padding = 9
else: # About 72% of the XO size, adjusted so that eg. toolbuttons work
    xo = False
    line_width = 2.0            # 1.62 rounded up
    thick_line_width = 3.0      # 2.52
    subcell_size = 11           # 10.8
    icon_base = 8               # 7.92
    bullet_size = 6.5           # 6.84
    # This is a guess on the font size (Sans 10 at 96 DPI)
    font_height = 17
    default_padding = 4         # 4.32
    toolbutton_padding = 6      # 7.68

# Radio size used to be:
#
# radio_size = my_floor(subcell_size + bullet_size + line_width)
#
# But a screenshot shows that the graphic was actually rendered at 26px
# so the SVG displays at the correct size.
# FIXME this only works for 100, has not been tested in 75 resolution
radio_size = 26
scale_slider_width = my_floor(2 * subcell_size + line_width)
thickness = my_ceil(line_width)

icon_small = icon_base * 3
icon_large = icon_base * 5

}

* {
    -sugar-focus-line: @white;

    background-color: @button_grey;
    color: @black;

    border-color: transparent;
    border-radius: 0px;
    border-style: none;

    padding: $(thickness)px;

    /* 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;

    /* we have to disable focus border for GtkTreeView, see #1261 */
    -GtkTreeView-interior-focus: 1;
    -GtkTreeView-focus-line-width: 0;

    -GtkTextView-interior-focus: 1;

    -GtkWidget-focus-line-width: 0;  /* Prevents some drawing glitches */
    -GtkEntry-focus-line-width: 0;
    -GtkScale-focus-line-width: 0;
    -GtkScale-focus-line-width: 0;
    -GtkWidget-focus-padding: 3;
    /* 0.05 works good for both the sugar and sugar-xo themes */
    -GtkWidget-cursor-aspect-ratio: 0.05;

    -GtkWidget-wide-separators: false;
    -GtkWidget-separator-height: $thickness;
    -GtkWidget-separator-width: $thickness;

    -GtkWidget-scroll-arrow-hlength: $subcell_size;
    -GtkWidget-scroll-arrow-vlength: $subcell_size;

    -GtkRange-activate-slider: 1;

    /* We fake the default border in the theme */
    -GtkButton-default-border: 0 0 0 0;
    -GtkButton-default-outside-border: 0 0 0 0;
    -GtkButton-image-spacing: $subcell_size;

    -GtkEntry-progress-border: $thickness $thickness $thickness $thickness;

    -GtkScrolledWindow-scrollbar-spacing: 0;

    -GtkExpander-expander-size: $font_height;
    -GtkExpander-expander-spacing: 2;

    -GtkTreeView-expander-size: $font_height;

    -GtkArrow-arrow-size: 1.0;

    -GtkToolbar-space-size: $(2*subcell_size);

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

    -GtkButtonBox-child-min-height: $(3*subcell_size);
    -GtkButtonBox-child-min-width: $(3*subcell_size);
    -GtkButtonBox-child-internal-pad-x: 0;
    -GtkButtonBox-child-internal-pad-y: 0;

    -GtkCheckButton-indicator-size: $radio_size;
    -GtkCheckButton-indicator-spacing: 3;
}

*:active {
    background-color: @white;
    color: @black;
}

/* Backgrounds and windows */

.background {
    padding: 0px;
    border-width: 0px;
    background-color: @panel_grey;
}

.window {
    background-color: @panel_grey;
    color: @black;
}

/* Handle this differently? */
.window *:insensitive {
    background-color: @panel_grey;
}

/* Buttons */

.button {
    ${ border = max(0, my_ceil((3*subcell_size/2.0 - icon_small / 2.0))) }
    /* It would be nicer to just set the inner-border, but that does not work
       for combo boxes ... The combobox ignores it, so set it to 0px
       See http://bugzilla.gnome.org/show_bug.cgi?id=485762 */

    -GtkButton-inner-border: 0 0 0 0;
    padding: $(border)px $(border)px $(border)px $(border)px;

    border-radius: $(2*subcell_size)px;
    background-color: @button_grey;
    color: @white;
}

.button * {
    color: @white;
}

.button:focused {
    border-width: $(thickness)px;
    border-color: @white;
    border-style: solid;
}

/* Spin buttons */

${ spin_ythickness = my_ceil(3*subcell_size - font_height) }
${ spin_xthickness = subcell_size }
${ spin_btn_ythickness = spin_ythickness }
${ spin_btn_xthickness = subcell_size * 2 }

.spinbutton.button,
.spinbutton.button:focused,
.spinbutton.button:active {
    padding: $(spin_ythickness)px $(spin_xthickness)px;
    border-color: @button_grey;
    border-width: $(thickness)px;
    background-color: @button_grey;
    color: @white;
}

.spinbutton.button:active {
    background-color: @white;
    color: @black;
    border-color: @white;
}

.spinbutton.button:insensitive {
    background-color: @selection_grey;
}

.spinbutton.button:focused,
.spinbutton.button:focused:prelight,
.spinbutton.button:focused:insensitive {
    border-color: @white;
}

/* Toggle buttons */

GtkToggleButton.button:active {
    background-color: @white;
}

GtkToggleButton.button:active GtkLabel {
    color: @black;
}

/* Entries and views */

.view {
    border-width: 0px;
    border-style: none;
    border-radius: 0px;
    padding: 0px;
    background-color: @white;
}

.entry {
    border-radius: $(2 * subcell_size)px;
    border-width: $(thickness)px;
    border-color: @selection_grey;
    border-style: solid;
    background-color: @text_field_grey;
    color: @black;
    ${ entry_ythickness = my_ceil(0.2 * (subcell_size*3.0/2.0 - thickness) + thickness) }
    ${ entry_xthickness = my_ceil(0.32 * (subcell_size*3.0/2.0 - thickness) + thickness) }
    padding: $(2 * max(my_ceil((3*subcell_size - font_height - entry_ythickness*2)/2.0),0))px $(2 * max(subcell_size - entry_xthickness, 0))px $(2 * max(my_floor((3*subcell_size - font_height - entry_ythickness*2)/2.0), 0))px $(2 * max(subcell_size - entry_xthickness, 0))px;
}

.entry.progressbar {
    border-radius: $(2 * subcell_size)px;
    border-width: $(thickness)px;
    background-color: @selection_grey;
}

.entry:focused {
    background-color: @white;
}

.entry:insensitive, .view:insensitive {
    background-color: @button_grey;
}

.view:selected {
    background-color: @panel_grey;
    color: @black;
}

.entry:selected, .entry:selected:focused,
.view:selected:focused {
    background-color: @selection_grey;
    color: @black;
}

/* Combo boxes */

GtkComboBox * {
    color: @white;
}

GtkComboBox .separator {
    /* Remove the separator turning it transparent */
    color: alpha(@theme_base_color, 0.0);
}

.toolbar GtkToggleButton.button:active,
SugarPaletteWindowWidget GtkToggleButton.button:active {
    background-color: @button_grey;
}

/* Notebooks */

.notebook {
    background-color: @selection_grey;
    border-width: 0px;
    -GtkNotebook-tab-overlap: -2;
    -GtkNotebook-tab-curvature: $default_padding;
}

.notebook tab,
.notebook tab GtkLabel {
    background-color: @button_grey;
    color: @white;
}

.notebook tab:active {
    background-color: @selection_grey;
}

/* Browse notebook */

BrowseNotebook.notebook tab {
    background-color: @selection_grey;
}

BrowseNotebook.notebook tab .button {
    border-radius: $(toolbutton_padding)px;
}

BrowseNotebook.notebook tab:active {
    background-color: @toolbar_grey;
}

BrowseNotebook.notebook tab:active *:active {
    color: @white;
}

BrowseLinkInfo {
    color: @white;
}

BrowseTabPage {
    background-color: @black;
}

/* Control panel */

SugarSectionView {
    background-color: @white;
    color: @black;
}

SugarSectionView *:insensitive {
    background-color: @white;
}

/* Alert */

SugarAlert {
    background-color: @black;
    color: @white;
}

SugarAlert *:insensitive {
    background-color: @black;
}

/* Tray */

SugarHTray * , SugarVTray * { background-color: @toolbar_grey;}

/* Menus and palettes */

SugarPaletteWindowWidget.background {
    background-color: @black;
}

SugarPaletteWindowWidget GtkLabel {
    color: @white;
}

SugarPaletteMenuWidget.background {
    background-color: @black;
}

SugarPaletteMenuWidget * {
    color: @white;
}

SugarPaletteWindow SugarGroupBox {
    background-color: @toolbar_grey;
    color: @white;
}

SugarPaletteWindow SugarGroupBox *:insensitive {
    background-color: @toolbar_grey;
}

.menu,
.palette {
    background-color: @black;
    color: @white;

    -GtkMenu-scroll-arrow-vlength: $(my_floor(subcell_size/0.7 + 2*thickness));
    -GtkMenu-horizontal-padding: $thickness;
    -GtkMenu-vertical-padding  : $thickness;
    /* This means the outline of the submenu overlaps with a palette.
     * However in the case of two normal menus, they are next to each other.
     * It is not possible to be smarter about this, because the style comes from
     * the submenu. */
    -GtkMenu-horizontal-offset : 0;
    -GtkMenu-vertical-offset   : 0;

    padding: 0px;
    border-width: 2px;
    border-color: @button_grey;
    border-style: solid;
}

.menu :prelight, palette :prelight {
    color: @white
}

.menu :active, palette :active {
    background-color: @button_grey;
}

.palette {
    padding: $(thickness)px;
}

.palette .menu {
    -GtkMenu-horizontal-padding: 0;
    -GtkMenu-vertical-padding: 0;

    padding: 0px $(subcell_size)px;
}

.menu * {
    color: @white;
}

GtkMenuItem {
    padding: $(subcell_size)px $((subcell_size * 3 - font_height) / 2)px;
}

/* Scrollbars */

.scrollbar {
    -GtkRange-slider-width: $subcell_size;
    -GtkRange-trough-border: 0;
    -GtkRange-stepper-size: 0;
    -GtkScrollbar-min-slider-length: $(3*subcell_size);
    -GtkScrollbar-has-forward-stepper: 0;
    -GtkScrollbar-has-backward-stepper: 0;
    -GtkScrollbar-has-secondary-forward-stepper: 0;
    -GtkScrollbar-has-secondary-backward-stepper: 0;
}

.scrollbar.trough {
    background-color: @button_grey;
    border-width: 0px;
}

.scrollbar.slider {
    background-color: @white;
    border-radius: $(2*subcell_size)px;
    border-width: 0px;
}

.scrollbar.slider:active {
    background-color: @text_field_grey;
}

/* Progress bars */

/* Scrollbar padding hack? What was that about? */

GtkProgressBar.progressbar {
    background-color: @white;
    border-color: @white;
    border-radius: 10px;
    border-style: solid;
    border-width: 0px;
}

GtkProgressBar.trough {
    background-color: alpha (@black, 0.0);
    border-style: solid;
    border-radius: 10px;
    border-color: @button_grey;
    border-width: 2px;
}

/* Separators */

GtkVSeparator, GtkHSeparator,
.toolbar GtkSeparatorToolItem {
    color: @button_grey;
}

/* Tool buttons */

.toolbar {
padding: 0px;
}

.toolbar GtkToolButton .button,
SugarPaletteWindowWidget GtkToolButton .button {
    border-radius: $(toolbutton_padding)px;
    padding: $(default_padding)px;
}

.toolbar GtkToolButton .button:prelight,
SugarPaletteWindowWidget GtkToolButton .button:prelight {
    background-color: @black;
    border-radius: 0px;
    border-width: 0px;
}

.toolbar GtkToolButton .button:active,
SugarPaletteWindowWidget GtkToolButton .button:active {
    background-color: @black;
    border-radius: 0px;
}

.toolbar GtkToolButton .button:active:prelight,
SugarPaletteWindowWidget GtkToolButton .button:active:prelight {
    background-color: @button_grey;
    border-radius: $(subcell_size)px;
    border-width: $(default_padding)px;
    border-color: transparent;
}

/* Scales */

GtkScale {
    -GtkScale-slider-length: $scale_slider_width;
    -GtkRange-slider-width: $scale_slider_width;
}

GtkScale.trough {
    border-style: solid;
    border-radius: 30px;
    border-color: @button_grey;
    border-width: 2px;
}

GtkScale.trough:focused {
    border-color: @white;
}

GtkScale.trough.top, GtkScale.trough.left {
    background-color: @white;
}

GtkScale.slider {
    color: alpha(@theme_base_color, 0.0);
    background-color: alpha(@theme_base_color, 0.0);
    background-image: url("assets/scale-slider.svg");
}

GtkScale.slider:active {
    color: alpha(@theme_base_color, 0.0);
    background-image: url("assets/scale-slider-active.svg");
}

/* Radio and check buttons */

GtkCheckButton:prelight {
    background-color: alpha(@theme_base_color, 0.0);
}

.radio,
.radio row:selected,
.radio row:selected:focused {
    background-image: url("assets/radio.svg");
    background-color: alpha(@theme_base_color, 0.0);
}

.radio:selected,
.radio:selected row:selected,
.radio:selected row:selected:focused {
    background-image: url("assets/radio-selected.svg");
}

.radio:active,
.radio row:selected:active,
.radio row:selected:focused:active {
    background-image: url("assets/radio-active.svg");
}

.radio:active:selected,
.radio:selected row:selected:active,
.radio:selected row:selected:focused:active {
    background-image: url("assets/radio-active-selected.svg");
}

.check,
.check row:selected,
.check row:selected:focused {
    background-image: url("assets/checkbox-unchecked.svg");
    background-color: alpha(@theme_base_color, 0.0);
}

.check:selected,
.check:selected row:selected,
.check:selected row:selected:focused {
    background-image: url("assets/checkbox-unchecked-selected.svg");
}

.check:active,
.check row:selected:active,
.check row:selected:focused:active {
    background-image: url("assets/checkbox-checked.svg");
}

.check:active:selected,
.check:selected row:selected:active,
.check:selected row:selected:focused:active {
    background-image: url("assets/checkbox-checked-selected.svg");
}

/* Tool items */

.toolitem {
    /* arrow in the toolbarbox */
    color: @white;
    /* outline of the toolbarbutton when palette is expanded */
    border-style: solid;
    border-width: 2px;
    border-color: @button_grey;
}

${
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 scaling == "100":
    xo = True
    line_width = 2.0        # 2.25px, rounded down
    thick_line_width = 3.5  # 3.5
    subcell_size = 15
    icon_base = 11
    bullet_size = 9.5
    font_height = 24
    default_padding = 6
    toolbutton_padding = 9
else: # About 72% of the XO size, adjusted so that eg. toolbuttons work
    xo = False
    line_width = 2.0            # 1.62 rounded up
    thick_line_width = 3.0      # 2.52
    subcell_size = 11           # 10.8
    icon_base = 8               # 7.92
    bullet_size = 6.5           # 6.84
    # This is a guess on the font size (Sans 10 at 96 DPI)
    font_height = 17
    default_padding = 4         # 4.32
    toolbutton_padding = 6      # 7.68

# Radio size used to be:
#
# radio_size = my_floor(subcell_size + bullet_size + line_width)
#
# But a screenshot shows that the graphic was actually rendered at 26px
# so the SVG displays at the correct size.
# FIXME this only works for 100, has not been tested in 75 resolution
radio_size = 26
scale_slider_width = my_floor(2 * subcell_size + line_width)
thickness = my_ceil(line_width)

icon_small = icon_base * 3
icon_large = icon_base * 5

}

* {
    -sugar-focus-line: @white;

    background-color: @button_grey;
    color: @black;

    border-color: transparent;
    border-radius: 0px;
    border-style: none;

    padding: $(thickness)px;

    /* 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;

    /* we have to disable focus border for GtkTreeView, see #1261 */
    -GtkTreeView-interior-focus: 1;
    -GtkTreeView-focus-line-width: 0;

    -GtkTextView-interior-focus: 1;

    -GtkWidget-focus-line-width: 0;  /* Prevents some drawing glitches */
    -GtkEntry-focus-line-width: 0;
    -GtkScale-focus-line-width: 0;
    -GtkScale-focus-line-width: 0;
    -GtkWidget-focus-padding: 3;
    /* 0.05 works good for both the sugar and sugar-xo themes */
    -GtkWidget-cursor-aspect-ratio: 0.05;

    -GtkWidget-wide-separators: false;
    -GtkWidget-separator-height: $thickness;
    -GtkWidget-separator-width: $thickness;

    -GtkWidget-scroll-arrow-hlength: $subcell_size;
    -GtkWidget-scroll-arrow-vlength: $subcell_size;

    -GtkRange-activate-slider: 1;

    /* We fake the default border in the theme */
    -GtkButton-default-border: 0 0 0 0;
    -GtkButton-default-outside-border: 0 0 0 0;
    -GtkButton-image-spacing: $subcell_size;

    -GtkEntry-progress-border: $thickness $thickness $thickness $thickness;

    -GtkScrolledWindow-scrollbar-spacing: 0;

    -GtkExpander-expander-size: $font_height;
    -GtkExpander-expander-spacing: 2;

    -GtkTreeView-expander-size: $font_height;

    -GtkArrow-arrow-size: 1.0;

    -GtkToolbar-space-size: $(2*subcell_size);

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

    -GtkButtonBox-child-min-height: $(3*subcell_size);
    -GtkButtonBox-child-min-width: $(3*subcell_size);
    -GtkButtonBox-child-internal-pad-x: 0;
    -GtkButtonBox-child-internal-pad-y: 0;

    -GtkCheckButton-indicator-size: $radio_size;
    -GtkCheckButton-indicator-spacing: 3;
}

*:active {
    background-color: @white;
    color: @black;
}

/* Backgrounds and windows */

.background {
    padding: 0px;
    border-width: 0px;
    background-color: @panel_grey;
}

.window {
    background-color: @panel_grey;
    color: @black;
}

/* Handle this differently? */
.window *:insensitive {
    background-color: @panel_grey;
}

/* Buttons */

.button {
    ${ border = max(0, my_ceil((3*subcell_size/2.0 - icon_small / 2.0))) }
    /* It would be nicer to just set the inner-border, but that does not work
       for combo boxes ... The combobox ignores it, so set it to 0px
       See http://bugzilla.gnome.org/show_bug.cgi?id=485762 */

    -GtkButton-inner-border: 0 0 0 0;
    padding: $(border)px $(border)px $(border)px $(border)px;

    border-radius: $(2*subcell_size)px;
    background-color: @button_grey;
    color: @white;
}

.button * {
    color: @white;
}

.button:focused {
    border-width: $(thickness)px;
    border-color: @white;
    border-style: solid;
}

/* Spin buttons */

${ spin_ythickness = my_ceil(3*subcell_size - font_height) }
${ spin_xthickness = subcell_size }
${ spin_btn_ythickness = spin_ythickness }
${ spin_btn_xthickness = subcell_size * 2 }

.spinbutton.button,
.spinbutton.button:focused,
.spinbutton.button:active {
    padding: $(spin_ythickness)px $(spin_xthickness)px;
    border-color: @button_grey;
    border-width: $(thickness)px;
    background-color: @button_grey;
    color: @white;
}

.spinbutton.button:active {
    background-color: @white;
    color: @black;
    border-color: @white;
}

.spinbutton.button:insensitive {
    background-color: @selection_grey;
}

.spinbutton.button:focused,
.spinbutton.button:focused:prelight,
.spinbutton.button:focused:insensitive {
    border-color: @white;
}

/* Toggle buttons */

GtkToggleButton.button:active {
    background-color: @white;
}

GtkToggleButton.button:active GtkLabel {
    color: @black;
}

/* Entries and views */

.view {
    border-width: 0px;
    border-style: none;
    border-radius: 0px;
    padding: 0px;
    background-color: @white;
}

.entry {
    border-radius: $(2 * subcell_size)px;
    border-width: $(thickness)px;
    border-color: @selection_grey;
    border-style: solid;
    background-color: @text_field_grey;
    color: @black;
    ${ entry_ythickness = my_ceil(0.2 * (subcell_size*3.0/2.0 - thickness) + thickness) }
    ${ entry_xthickness = my_ceil(0.32 * (subcell_size*3.0/2.0 - thickness) + thickness) }
    padding: $(2 * max(my_ceil((3*subcell_size - font_height - entry_ythickness*2)/2.0),0))px $(2 * max(subcell_size - entry_xthickness, 0))px $(2 * max(my_floor((3*subcell_size - font_height - entry_ythickness*2)/2.0), 0))px $(2 * max(subcell_size - entry_xthickness, 0))px;
}

.entry.progressbar {
    border-radius: $(2 * subcell_size)px;
    border-width: $(thickness)px;
    background-color: @selection_grey;
}

.entry:focused {
    background-color: @white;
}

.entry:insensitive, .view:insensitive {
    background-color: @button_grey;
}

.view:selected {
    background-color: @panel_grey;
    color: @black;
}

.entry:selected, .entry:selected:focused,
.view:selected:focused {
    background-color: @selection_grey;
    color: @black;
}

/* Combo boxes */

GtkComboBox * {
    color: @white;
}

GtkComboBox .separator {
    /* Remove the separator turning it transparent */
    color: alpha(@theme_base_color, 0.0);
}

.toolbar GtkToggleButton.button:active,
SugarPaletteWindowWidget GtkToggleButton.button:active {
    background-color: @button_grey;
}

/* Notebooks */

.notebook {
    background-color: @selection_grey;
    border-width: 0px;
    -GtkNotebook-tab-overlap: -2;
    -GtkNotebook-tab-curvature: $default_padding;
}

.notebook tab,
.notebook tab GtkLabel {
    background-color: @button_grey;
    color: @white;
}

.notebook tab:active {
    background-color: @selection_grey;
}

/* Browser notebook */

BrowserNotebook.notebook tab {
    background-color: @selection_grey;
}

BrowserNotebook.notebook tab .button {
    border-radius: $(toolbutton_padding)px;
}

BrowserNotebook.notebook tab:active {
    background-color: @toolbar_grey;
}

BrowserNotebook.notebook tab:active *:active {
    color: @white;
}

/* Control panel */

SugarSectionView {
    background-color: @white;
    color: @black;
}

SugarSectionView *:insensitive {
    background-color: @white;
}

/* Alert */

SugarAlert {
    background-color: @black;
    color: @white;
}

SugarAlert *:insensitive {
    background-color: @black;
}

/* Tray */

SugarHTray * , SugarVTray * { background-color: @toolbar_grey;}

/* Menus and palettes */

SugarPaletteWindowWidget.background {
    background-color: @black;
}

SugarPaletteWindowWidget GtkLabel {
    color: @white;
}

SugarPaletteMenuWidget.background {
    background-color: @black;
}

SugarPaletteMenuWidget * {
    color: @white;
}

SugarPaletteWindow SugarGroupBox {
    background-color: @toolbar_grey;
    color: @white;
}

SugarPaletteWindow SugarGroupBox *:insensitive {
    background-color: @toolbar_grey;
}

.menu,
.palette {
    background-color: @black;
    color: @white;

    -GtkMenu-scroll-arrow-vlength: $(my_floor(subcell_size/0.7 + 2*thickness));
    -GtkMenu-horizontal-padding: $thickness;
    -GtkMenu-vertical-padding  : $thickness;
    /* This means the outline of the submenu overlaps with a palette.
     * However in the case of two normal menus, they are next to each other.
     * It is not possible to be smarter about this, because the style comes from
     * the submenu. */
    -GtkMenu-horizontal-offset : 0;
    -GtkMenu-vertical-offset   : 0;

    padding: 0px;
    border-width: 2px;
    border-color: @button_grey;
    border-style: solid;
}

.menu :prelight, palette :prelight {
    color: @white
}

.menu :active, palette :active {
    background-color: @button_grey;
}

.palette {
    padding: $(thickness)px;
}

.palette .menu {
    -GtkMenu-horizontal-padding: 0;
    -GtkMenu-vertical-padding: 0;

    padding: 0px $(subcell_size)px;
}

.menu * {
    color: @white;
}

GtkMenuItem {
    padding: $(subcell_size)px $((subcell_size * 3 - font_height) / 2)px;
}

/* Scrollbars */

.scrollbar {
    -GtkRange-slider-width: $subcell_size;
    -GtkRange-trough-border: 0;
    -GtkRange-stepper-size: 0;
    -GtkScrollbar-min-slider-length: $(3*subcell_size);
    -GtkScrollbar-has-forward-stepper: 0;
    -GtkScrollbar-has-backward-stepper: 0;
    -GtkScrollbar-has-secondary-forward-stepper: 0;
    -GtkScrollbar-has-secondary-backward-stepper: 0;
}

.scrollbar.trough {
    background-color: @button_grey;
    border-width: 0px;
}

.scrollbar.slider {
    background-color: @white;
    border-radius: $(2*subcell_size)px;
    border-width: 0px;
}

.scrollbar.slider:active {
    background-color: @text_field_grey;
}

/* Progress bars */

/* Scrollbar padding hack? What was that about? */

GtkProgressBar.progressbar {
    background-color: @white;
    border-color: @white;
    border-radius: 10px;
    border-style: solid;
    border-width: 0px;
}

GtkProgressBar.trough {
    background-color: alpha (@black, 0.0);
    border-style: solid;
    border-radius: 10px;
    border-color: @button_grey;
    border-width: 2px;
}

/* Separators */

GtkVSeparator, GtkHSeparator,
.toolbar GtkSeparatorToolItem {
    color: @button_grey;
}

/* Tool buttons */

.toolbar {
padding: 0px;
}

.toolbar GtkToolButton .button,
SugarPaletteWindowWidget GtkToolButton .button {
    border-radius: $(toolbutton_padding)px;
    padding: $(default_padding)px;
}

.toolbar GtkToolButton .button:prelight,
SugarPaletteWindowWidget GtkToolButton .button:prelight {
    background-color: @black;
    border-radius: 0px;
    border-width: 0px;
}

.toolbar GtkToolButton .button:active,
SugarPaletteWindowWidget GtkToolButton .button:active {
    background-color: @black;
    border-radius: 0px;
}

.toolbar GtkToolButton .button:active:prelight,
SugarPaletteWindowWidget GtkToolButton .button:active:prelight {
    background-color: @button_grey;
    border-radius: $(subcell_size)px;
    border-width: $(default_padding)px;
    border-color: transparent;
}

/* Scales */

GtkScale {
    -GtkScale-slider-length: $scale_slider_width;
    -GtkRange-slider-width: $scale_slider_width;
}

GtkScale.trough {
    border-style: solid;
    border-radius: 30px;
    border-color: @button_grey;
    border-width: 2px;
}

GtkScale.trough:focused {
    border-color: @white;
}

GtkScale.trough.top, GtkScale.trough.left {
    background-color: @white;
}

GtkScale.slider {
    color: alpha(@theme_base_color, 0.0);
    background-color: alpha(@theme_base_color, 0.0);
    background-image: url("assets/scale-slider.svg");
}

GtkScale.slider:active {
    color: alpha(@theme_base_color, 0.0);
    background-image: url("assets/scale-slider-active.svg");
}

/* Radio and check buttons */

GtkCheckButton:prelight {
    background-color: alpha(@theme_base_color, 0.0);
}

.radio,
.radio row:selected,
.radio row:selected:focused {
    background-image: url("assets/radio.svg");
    background-color: alpha(@theme_base_color, 0.0);
}

.radio:selected,
.radio:selected row:selected,
.radio:selected row:selected:focused {
    background-image: url("assets/radio-selected.svg");
}

.radio:active,
.radio row:selected:active,
.radio row:selected:focused:active {
    background-image: url("assets/radio-active.svg");
}

.radio:active:selected,
.radio:selected row:selected:active,
.radio:selected row:selected:focused:active {
    background-image: url("assets/radio-active-selected.svg");
}

.check,
.check row:selected,
.check row:selected:focused {
    background-image: url("assets/checkbox-unchecked.svg");
    background-color: alpha(@theme_base_color, 0.0);
}

.check:selected,
.check:selected row:selected,
.check:selected row:selected:focused {
    background-image: url("assets/checkbox-unchecked-selected.svg");
}

.check:active,
.check row:selected:active,
.check row:selected:focused:active {
    background-image: url("assets/checkbox-checked.svg");
}

.check:active:selected,
.check:selected row:selected:active,
.check:selected row:selected:focused:active {
    background-image: url("assets/checkbox-checked-selected.svg");
}

/* Tool items */

.toolitem {
    /* arrow in the toolbarbox */
    color: @white;
    /* outline of the toolbarbutton when palette is expanded */
    border-style: solid;
    border-width: 2px;
    border-color: @button_grey;
}


Ignore the seccomp profile warning in `docker info`. (#527)

When using a custom seccomp profile a warning is printed in docker info.

Connects to
https://github.com/ros-infrastructure/buildfarm_deployment/issues/176.

@(SNIPPET(
    'builder_system-groovy',
    command=
"""// EXTRACT WARNINGS AND MARK BUILD UNSTABLE
import java.io.BufferedReader
import java.util.regex.Matcher
import java.util.regex.Pattern

import hudson.model.Result

println "# BEGIN SECTION: Look for warnings"

try {
  // search build output for warning messages
  r = build.getLogReader()
  br = new BufferedReader(r)
  pattern = Pattern.compile(".*WARNING:.*")
  ignore_pattern = Pattern.compile(".*WARNING: (You're not using the default seccomp profile|No swap limit support).*")
  def warnings = []
  def line
  while ((line = br.readLine()) != null) {
    if (pattern.matcher(line).matches()) {
      if (ignore_pattern.matcher(line).matches()) continue
      warnings << line
    }
  }
  if (warnings.size() == 0) {
    println "No warnings found"
  } else {
    println "Found " + warnings.size() + " warnings:"
    println ""
    for (warning in warnings) {
      println "- " + warning
      println ""
    }
    if (build.getResult().isBetterThan(Result.UNSTABLE)) {
      println "Marking build as unstable"
      build.setResult(Result.UNSTABLE)
    }
  }
} finally {
  println "# END SECTION"
}
""",
    script_file=None,
))@

@(SNIPPET(
    'builder_system-groovy',
    command=
"""// EXTRACT WARNINGS AND MARK BUILD UNSTABLE
import java.io.BufferedReader
import java.util.regex.Matcher
import java.util.regex.Pattern

import hudson.model.Result

println "# BEGIN SECTION: Look for warnings"

try {
  // search build output for warning messages
  r = build.getLogReader()
  br = new BufferedReader(r)
  pattern = Pattern.compile(".*WARNING:.*")
  ignore_pattern = Pattern.compile(".*WARNING: No swap limit support.*")
  def warnings = []
  def line
  while ((line = br.readLine()) != null) {
    if (pattern.matcher(line).matches()) {
      if (ignore_pattern.matcher(line).matches()) continue
      warnings << line
    }
  }
  if (warnings.size() == 0) {
    println "No warnings found"
  } else {
    println "Found " + warnings.size() + " warnings:"
    println ""
    for (warning in warnings) {
      println "- " + warning
      println ""
    }
    if (build.getResult().isBetterThan(Result.UNSTABLE)) {
      println "Marking build as unstable"
      build.setResult(Result.UNSTABLE)
    }
  }
} finally {
  println "# END SECTION"
}
""",
    script_file=None,
))@


Small eol tweek for userend consistency.

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@

# setup source.list to eol
RUN sed -i -e 's/archive/old-releases/g' /etc/apt/sources.list

@[if 'packages' in locals()]@
@[if packages]@

# install packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    @(' \\\n    '.join(packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[end if]@
@[end if]@
# setup keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros/ubuntu @os_code_name main" > /etc/apt/sources.list.d/ros-latest.list

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# install ros packages
ENV ROS_DISTRO @rosdistro_name
RUN apt-get update && apt-get install -y \
    @(' \\\n    '.join(ros_packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[if 'entrypoint_name' in locals()]@
@[if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /ros_entrypoint.sh

ENTRYPOINT ["/ros_entrypoint.sh"]
@[end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@

# setup source.list to eol
RUN sed -i -e 's/archive/old-releases/g' /etc/apt/sources.list

@[if 'packages' in locals()]@
@[if packages]@

# install packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    @(' \\\n    '.join(packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[end if]@
@[end if]@
# setup keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros/ubuntu @os_code_name main" > /etc/apt/sources.list.d/ros-latest.list

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# install ros packages
ENV ROS_DISTRO @rosdistro_name
RUN apt-get update && apt-get install -y \
    @(' \\\n    '.join(ros_packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[if 'entrypoint_name' in locals()]@
@[if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]


Have ros2 images closer conform to ros1 image style

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@

# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN . /etc/os-release \
    && echo "deb http://repo.ros2.org/$ID/main `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

# install bootstrap tools
RUN apt-get update && apt-get install --no-install-recommends -y \
    python3-rosdep \
    python3-rosinstall \
    python3-vcstools \
    && rm -rf /var/lib/apt/lists/*

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# bootstrap rosdep
ENV ROSDISTRO_INDEX_URL https://raw.githubusercontent.com/ros2/rosdistro/ros2/index.yaml
RUN rosdep init \
    && rosdep update

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

# install ros2 packages
ENV ROS_DISTRO @ros2distro_name
RUN apt-get update && apt-get install -y \
    @(' \\\n    '.join(ros2_packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@

# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN . /etc/os-release \
    && echo "deb http://repo.ros2.org/$ID/main `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

ENV ROS_DISTRO @ros2distro_name

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

@[if 'ros2_packages' in locals()]@
@[  if ros2_packages]@
# install ros2 packages
RUN apt-get update && apt-get install -y \
    @(' \\\n    '.join(ros2_packages))@  \
    && rm -rf /var/lib/apt/lists/*

@[  end if]@
@[end if]@
@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]


fixed relative path

fixed relative path

#!/bin/bash

# DO NOT REMOVE THIS BLOCK UNLESS YOU DON'T WANT TO USE CUSTOM SCRIPTS
@[if DEVELSPACE]@
export ROSWSS_SCRIPTS="@(PROJECT_SOURCE_DIR)/scripts:$ROSWSS_SCRIPTS"
@[else]@
export ROSWSS_SCRIPTS="@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts:$ROSWSS_SCRIPTS"
@[end if]@

# SET HERE YOUR WORKSPACE PREFIX
export ROSWSS_PREFIX="thor"
export ROSWSS_ROOT_RELATIVE_PATH="../.."

# SETUP YOUR ENVIRONMENT HERE
export ONBOARD_LAUNCH_PKG="thor_mang_onboard_launch"
export GAZEBO_LAUNCH_PKG="thor_mang_gazebo"
export GAZEBO_WORLDS_PKG="thor_mang_gazebo"
export ROBOT_MASTER_HOSTNANE="thor-motion"
export ROBOT_HOSTNAMES="thor-motion thor-perception thor-onboard"
export ROBOT_USER="thor"

# THOR SPECIFIC EXPORTS
export GAZEBO_MODEL_PATH=$WS_ROOT/src/thor/thor_mang_simulation/thor_mang_gazebo/models
export THOR_MOTION_HOSTNAME="thor-motion"
export THOR_PERCEPTION_HOSTNAME="thor-perception"
export THOR_ONBOARD_HOSTNAME="thor-perception"

# THOR PCs/LAUNCHES
add_remote_pc "motion" "thor-motion" "motion" "roslaunch thor_mang_onboard_launch motion.launch"
add_remote_pc "perception" "thor-perception" "perception" "export ROS_MASTER_URI=http://thor-motion:11311; export ROS_IP=192.168.1.11; roslaunch thor_mang_onboard_launch perception.launch"
add_remote_pc "onboard" "thor-motion" "onboard" "export ROS_MASTER_URI=http://thor-motion:11311; export ROS_IP=192.168.1.11; roslaunch thor_mang_onboard_launch onboard.launch"

# Custom completion scripts
add_completion "ui" "_ui_complete"

#!/bin/bash

# DO NOT REMOVE THIS BLOCK UNLESS YOU DON'T WANT TO USE CUSTOM SCRIPTS
@[if DEVELSPACE]@
export ROSWSS_SCRIPTS="@(PROJECT_SOURCE_DIR)/scripts:$ROSWSS_SCRIPTS"
@[else]@
export ROSWSS_SCRIPTS="@(CMAKE_INSTALL_PREFIX)/@(CATKIN_PACKAGE_SHARE_DESTINATION)/scripts:$ROSWSS_SCRIPTS"
@[end if]@

# SET HERE YOUR WORKSPACE PREFIX
export ROSWSS_PREFIX="thor"
export ROSWSS_ROOT_RELATIVE_PATH="../../.."

# SETUP YOUR ENVIRONMENT HERE
export ONBOARD_LAUNCH_PKG="thor_mang_onboard_launch"
export GAZEBO_LAUNCH_PKG="thor_mang_gazebo"
export GAZEBO_WORLDS_PKG="thor_mang_gazebo"
export ROBOT_MASTER_HOSTNANE="thor-motion"
export ROBOT_HOSTNAMES="thor-motion thor-perception thor-onboard"
export ROBOT_USER="thor"

# THOR SPECIFIC EXPORTS
export GAZEBO_MODEL_PATH=$WS_ROOT/src/thor/thor_mang_simulation/thor_mang_gazebo/models
export THOR_MOTION_HOSTNAME="thor-motion"
export THOR_PERCEPTION_HOSTNAME="thor-perception"
export THOR_ONBOARD_HOSTNAME="thor-perception"

# THOR PCs/LAUNCHES
add_remote_pc "motion" "thor-motion" "motion" "roslaunch thor_mang_onboard_launch motion.launch"
add_remote_pc "perception" "thor-perception" "perception" "export ROS_MASTER_URI=http://thor-motion:11311; export ROS_IP=192.168.1.11; roslaunch thor_mang_onboard_launch perception.launch"
add_remote_pc "onboard" "thor-motion" "onboard" "export ROS_MASTER_URI=http://thor-motion:11311; export ROS_IP=192.168.1.11; roslaunch thor_mang_onboard_launch onboard.launch"

# Custom completion scripts
add_completion "ui" "_ui_complete"


version -> ros_version

version -> ros_version

Signed-off-by: Mikael Arguedas <a16f295d1139a1392bb19262902c32cf3e999ce4@gmail.com>

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
    'wget',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@
# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

@(TEMPLATE(
    'snippet/install_ros_bootstrap_tools.Dockerfile.em',
    ros_version=ros_version,
))@

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# bootstrap rosdep
RUN rosdep init \
    && rosdep update

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

# install ros2 packages
ENV ROS_DISTRO @ros2distro_name
RUN mkdir -p /opt/ros/$ROS_DISTRO
ARG ROS2_BINARY_URL=@ros2_binary_url
RUN wget -q $ROS2_BINARY_URL -O - | \
    tar -xj --strip-components=1 -C /opt/ros/$ROS_DISTRO

@[if 'rosdep_override' in locals()]@
# add custom rosdep rule files
@[  for rule_file in rosdep_override]@
COPY @rule_file /etc/ros/rosdep/
RUN echo "yaml file:///etc/ros/rosdep/@rule_file" | \
    cat - /etc/ros/rosdep/sources.list.d/20-default.list > temp && \
    mv temp /etc/ros/rosdep/sources.list.d/20-default.list
@[  end for]@
RUN rosdep update

@[end if]@
@
@[if 'rosdep' in locals()]@
@[  if 'install' in rosdep]@
@(TEMPLATE(
    'snippet/install_rosdep_dependencies.Dockerfile.em',
    install_args=rosdep['install'],
))@

@[  end if]@
@[end if]@
@
# install setup files
RUN apt-get update && apt-get install -q -y \
    ros-$ROS_DISTRO-ros-workspace \
    && rm -rf /var/lib/apt/lists/*

# FIXME Remove this once rosdep detects ROS 2 packages https://github.com/ros-infrastructure/rosdep/issues/660
# ignore installed rosdep keys
ENV ROS_PACKAGE_PATH /opt/ros/$ROS_DISTRO/share

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
    'wget',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@
# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

@(TEMPLATE(
    'snippet/install_ros_bootstrap_tools.Dockerfile.em',
    ros_version=version,
))@

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# bootstrap rosdep
RUN rosdep init \
    && rosdep update

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

# install ros2 packages
ENV ROS_DISTRO @ros2distro_name
RUN mkdir -p /opt/ros/$ROS_DISTRO
ARG ROS2_BINARY_URL=@ros2_binary_url
RUN wget -q $ROS2_BINARY_URL -O - | \
    tar -xj --strip-components=1 -C /opt/ros/$ROS_DISTRO

@[if 'rosdep_override' in locals()]@
# add custom rosdep rule files
@[  for rule_file in rosdep_override]@
COPY @rule_file /etc/ros/rosdep/
RUN echo "yaml file:///etc/ros/rosdep/@rule_file" | \
    cat - /etc/ros/rosdep/sources.list.d/20-default.list > temp && \
    mv temp /etc/ros/rosdep/sources.list.d/20-default.list
@[  end for]@
RUN rosdep update

@[end if]@
@
@[if 'rosdep' in locals()]@
@[  if 'install' in rosdep]@
@(TEMPLATE(
    'snippet/install_rosdep_dependencies.Dockerfile.em',
    install_args=rosdep['install'],
))@

@[  end if]@
@[end if]@
@
# install setup files
RUN apt-get update && apt-get install -q -y \
    ros-$ROS_DISTRO-ros-workspace \
    && rm -rf /var/lib/apt/lists/*

# FIXME Remove this once rosdep detects ROS 2 packages https://github.com/ros-infrastructure/rosdep/issues/660
# ignore installed rosdep keys
ENV ROS_PACKAGE_PATH /opt/ros/$ROS_DISTRO/share

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]


source ros-workspace before calling rosdep

Signed-off-by: Mikael Arguedas <a16f295d1139a1392bb19262902c32cf3e999ce4@gmail.com>

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
    'wget',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@
# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

@(TEMPLATE(
    'snippet/install_ros_bootstrap_tools.Dockerfile.em',
    ros_version=ros_version,
))@

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# bootstrap rosdep
RUN rosdep init \
    && rosdep update

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

# install ros2 packages
ENV ROS_DISTRO @ros2distro_name
RUN mkdir -p /opt/ros/$ROS_DISTRO
ARG ROS2_BINARY_URL=@ros2_binary_url
RUN wget -q $ROS2_BINARY_URL -O - | \
    tar -xj --strip-components=1 -C /opt/ros/$ROS_DISTRO

# install setup files
RUN apt-get update && apt-get install -q -y \
    ros-$ROS_DISTRO-ros-workspace \
    && rm -rf /var/lib/apt/lists/*

@[if 'rosdep_override' in locals()]@
# add custom rosdep rule files
@[  for rule_file in rosdep_override]@
COPY @rule_file /etc/ros/rosdep/
RUN echo "yaml file:///etc/ros/rosdep/@rule_file" | \
    cat - /etc/ros/rosdep/sources.list.d/20-default.list > temp && \
    mv temp /etc/ros/rosdep/sources.list.d/20-default.list
@[  end for]@
RUN rosdep update

@[end if]@
@
@[if 'rosdep' in locals()]@
@{
if 'path' not in rosdep:
  rosdep['path']='/opt/ros/$ROS_DISTRO/share'
}@
# install dependencies
RUN . /opt/ros/$ROS_DISTRO/setup.sh \
    && apt-get update \
    && rosdep install -y \
    --from-paths @(rosdep['path']) \
    --ignore-src \
    --skip-keys " \
      @(' \\\n      '.join(rosdep['skip_keys']))@ " \
    && rm -rf /var/lib/apt/lists/*

@[end if]@
@
# FIXME Remove this once rosdep detects ROS 2 packages https://github.com/ros-infrastructure/rosdep/issues/660
# ignore installed rosdep keys
ENV ROS_PACKAGE_PATH /opt/ros/$ROS_DISTRO/share

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]

@(TEMPLATE(
    'snippet/add_generated_comment.Dockerfile.em',
    user_name=user_name,
    tag_name=tag_name,
    source_template_name=template_name,
))@
@(TEMPLATE(
    'snippet/from_base_image.Dockerfile.em',
    template_packages=template_packages,
    os_name=os_name,
    os_code_name=os_code_name,
    arch=arch,
    base_image=base_image,
    maintainer_name=maintainer_name,
))@
@(TEMPLATE(
    'snippet/setup_tzdata.Dockerfile.em',
    os_name=os_name,
    os_code_name=os_code_name,
))@
@{
template_dependencies = [
    'dirmngr',
    'gnupg2',
    'lsb-release',
    'wget',
]
# add 'python3-pip' to 'template_dependencies' if pip dependencies are declared
if 'pip3_install' in locals():
    if isinstance(pip3_install, list) and pip3_install != []:
        template_dependencies.append('python3-pip')
}@
@(TEMPLATE(
    'snippet/install_upstream_package_list.Dockerfile.em',
    packages=template_dependencies,
    upstream_packages=upstream_packages if 'upstream_packages' in locals() else [],
))@
@
# setup ros2 keys
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 421C365BD9FF1F717815A3895523BAEEB01FA116

# setup sources.list
RUN echo "deb http://packages.ros.org/ros2/ubuntu `lsb_release -sc` main" > /etc/apt/sources.list.d/ros2-latest.list

@(TEMPLATE(
    'snippet/install_ros_bootstrap_tools.Dockerfile.em',
    ros_version=ros_version,
))@

# setup environment
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# bootstrap rosdep
RUN rosdep init \
    && rosdep update

@[if 'pip3_install' in locals()]@
@[  if pip3_install]@
# install python packages
RUN pip3 install -U \
    @(' \\\n    '.join(pip3_install))@

@[  end if]@
@[end if]@

# install ros2 packages
ENV ROS_DISTRO @ros2distro_name
RUN mkdir -p /opt/ros/$ROS_DISTRO
ARG ROS2_BINARY_URL=@ros2_binary_url
RUN wget -q $ROS2_BINARY_URL -O - | \
    tar -xj --strip-components=1 -C /opt/ros/$ROS_DISTRO

@[if 'rosdep_override' in locals()]@
# add custom rosdep rule files
@[  for rule_file in rosdep_override]@
COPY @rule_file /etc/ros/rosdep/
RUN echo "yaml file:///etc/ros/rosdep/@rule_file" | \
    cat - /etc/ros/rosdep/sources.list.d/20-default.list > temp && \
    mv temp /etc/ros/rosdep/sources.list.d/20-default.list
@[  end for]@
RUN rosdep update

@[end if]@
@
@[if 'rosdep' in locals()]@
@[  if 'install' in rosdep]@
@(TEMPLATE(
    'snippet/install_rosdep_dependencies.Dockerfile.em',
    install_args=rosdep['install'],
))@

@[  end if]@
@[end if]@
@
# install setup files
RUN apt-get update && apt-get install -q -y \
    ros-$ROS_DISTRO-ros-workspace \
    && rm -rf /var/lib/apt/lists/*

# FIXME Remove this once rosdep detects ROS 2 packages https://github.com/ros-infrastructure/rosdep/issues/660
# ignore installed rosdep keys
ENV ROS_PACKAGE_PATH /opt/ros/$ROS_DISTRO/share

@[if 'entrypoint_name' in locals()]@
@[  if entrypoint_name]@
@{
entrypoint_file = entrypoint_name.split('/')[-1]
}@
# setup entrypoint
COPY ./@entrypoint_file /

ENTRYPOINT ["/@entrypoint_file"]
@[  end if]@
@[end if]@
@{
cmds = [
'bash',
]
}@
CMD ["@(' && '.join(cmds))"]


microRTPS_timesync.h: fix comments notation so to be properly generated in EmPy

@###############################################
@#
@# EmPy template for generating microRTPS_timesync.h file
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - msgs (List) list of all msg files
@#  - multi_topics (List) list of all multi-topic names
@#  - ids (List) list of all RTPS msg ids
@###############################################
@{
import genmsg.msgs

from px_generate_uorb_topic_helper import * # this is in Tools/
from px_generate_uorb_topic_files import MsgScope # this is in Tools/

package = package[0]
fastrtpsgen_version = fastrtpsgen_version[0]
try:
    ros2_distro = ros2_distro[0].decode("utf-8")
except AttributeError:
    ros2_distro = ros2_distro[0]
}@
/****************************************************************************
 *
 * Copyright (c) 2020 PX4 Development 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:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 *
 ****************************************************************************/

/*!
 * @@file microRTPS_timesync.h
 * @@brief Adds time sync for the microRTPS bridge
 * @@author Nuno Marques <nuno.marques@@dronesolutions.io>
 * @@author Julian Kent <julian@@auterion.com>
 */

#pragma once

#include <atomic>
#include <functional>
#include <thread>

@[if ros2_distro]@
#include "Timesync_Publisher.h"
#include "Timesync_Subscriber.h"
@[else]@
#include "timesync_Publisher.h"
#include "timesync_Subscriber.h"
@[end if]@

static constexpr double ALPHA_INITIAL = 0.05;
static constexpr double ALPHA_FINAL = 0.003;
static constexpr double BETA_INITIAL = 0.05;
static constexpr double BETA_FINAL = 0.003;
static constexpr int WINDOW_SIZE = 500;
static constexpr int64_t UNKNOWN = 0;
static constexpr int64_t TRIGGER_RESET_THRESHOLD_NS = 100ll * 1000ll * 1000ll;
static constexpr int REQUEST_RESET_COUNTER_THRESHOLD = 5;

class TimeSync {
public:
	TimeSync();
	virtual ~TimeSync();

@[if ros2_distro]@
	void start(const Timesync_Publisher* pub);
@[else]@
	void start(const timesync_Publisher* pub);
@[end if]@

	void reset();
	void stop();

	/**
	 * Get clock monotonic time (raw) in nanoseconds
	 */
	inline int64_t getMonoRawTimeNSec() {
		timespec t;
		clock_gettime(CLOCK_MONOTONIC_RAW, &t);
		return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
	}

	/**
	 * Get system monotonic time in microseconds
	 */
	inline int64_t getMonoTimeUSec() {
		timespec t;
		clock_gettime(CLOCK_MONOTONIC, &t);
		return (int64_t)(t.tv_sec * 1000000000LL + t.tv_nsec) / 1000LL;
	}

	bool addMeasurement(int64_t local_t1_ns, int64_t remote_t2_ns, int64_t local_t3_ns);

@[if 1.5 <= fastrtpsgen_version <= 1.7]@
@[    if ros2_distro]@
	void processTimesyncMsg(@(package)::msg::dds_::Timesync_* msg);

	@(package)::msg::dds_::Timesync_ newTimesyncMsg();
@[    else]@
	void processTimesyncMsg(timesync_* msg);

	timesync_ newTimesyncMsg();
@[    end if]@
@[else]@
@[    if ros2_distro]@
	void processTimesyncMsg(@(package)::msg::Timesync* msg);

	@(package)::msg::Timesync newTimesyncMsg();
@[    else]@
	void processTimesyncMsg(timesync* msg);

	timesync newTimesyncMsg();
@[    end if]@
@[end if]@

	/**
	 * @@brief Get the time sync offset in nanoseconds
	 * @@return The offset in nanosecods
	 */
	inline int64_t getOffset() { return _offset_ns.load(); }

	/**
	 * @@brief Sums the time sync offset to the timestamp
	 * @@param[in,out] timestamp The timestamp to add the offset to
	 */
	inline void addOffset(uint64_t& timestamp) { timestamp = (timestamp * 1000LL + _offset_ns.load()) / 1000ULL; }

	/**
	 * @@brief Substracts the time sync offset to the timestamp
	 * @@param[in,out] timestamp The timestamp to subtract the offset of
	 */
	inline void subtractOffset(uint64_t& timestamp) { timestamp = (timestamp * 1000LL - _offset_ns.load()) / 1000ULL; }

private:
	std::atomic<int64_t> _offset_ns;
	int64_t _skew_ns_per_sync;
	int64_t _num_samples;

	int32_t _request_reset_counter;
	uint8_t _last_msg_seq;
	uint8_t _last_remote_msg_seq;

@[if ros2_distro]@
	Timesync_Publisher _timesync_pub;
	Timesync_Subscriber _timesync_sub;
@[else]@
	timesync_Publisher _timesync_pub;
	timesync_Subscriber _timesync_sub;
@[end if]@

	std::unique_ptr<std::thread> _send_timesync_thread;
	std::atomic<bool> _request_stop{false};

	/**
	 * @@brief Updates the offset of the time sync filter
	 * @@param[in] offset The value of the offset to update to
	 */
	inline void updateOffset(const uint64_t& offset) { _offset_ns.store(offset, std::memory_order_relaxed); }
};

@###############################################
@#
@# EmPy template for generating microRTPS_timesync.h file
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - msgs (List) list of all msg files
@#  - multi_topics (List) list of all multi-topic names
@#  - ids (List) list of all RTPS msg ids
@###############################################
@{
import genmsg.msgs

from px_generate_uorb_topic_helper import * # this is in Tools/
from px_generate_uorb_topic_files import MsgScope # this is in Tools/

package = package[0]
fastrtpsgen_version = fastrtpsgen_version[0]
try:
    ros2_distro = ros2_distro[0].decode("utf-8")
except AttributeError:
    ros2_distro = ros2_distro[0]
}@
/****************************************************************************
 *
 * Copyright (c) 2020 PX4 Development 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:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 *
 ****************************************************************************/

/*!
 * @@file microRTPS_timesync.h
 * @@brief Adds time sync for the microRTPS bridge
 * @@author Nuno Marques <nuno.marques@@dronesolutions.io>
 * @@author Julian Kent <julian@@auterion.com>
 */

#pragma once

#include <atomic>
#include <functional>
#include <thread>

@[if ros2_distro]@
#include "Timesync_Publisher.h"
#include "Timesync_Subscriber.h"
@[else]@
#include "timesync_Publisher.h"
#include "timesync_Subscriber.h"
@[end if]@

static constexpr double ALPHA_INITIAL = 0.05;
static constexpr double ALPHA_FINAL = 0.003;
static constexpr double BETA_INITIAL = 0.05;
static constexpr double BETA_FINAL = 0.003;
static constexpr int WINDOW_SIZE = 500;
static constexpr int64_t UNKNOWN = 0;
static constexpr int64_t TRIGGER_RESET_THRESHOLD_NS = 100ll * 1000ll * 1000ll;
static constexpr int REQUEST_RESET_COUNTER_THRESHOLD = 5;

class TimeSync {
public:
	TimeSync();
	virtual ~TimeSync();

@[if ros2_distro]@
	void start(const Timesync_Publisher* pub);
@[else]@
	void start(const timesync_Publisher* pub);
@[end if]@

	void reset();
	void stop();

	/**
	 * Get clock monotonic time (raw) in nanoseconds
	 */
	inline int64_t getMonoRawTimeNSec() {
		timespec t;
		clock_gettime(CLOCK_MONOTONIC_RAW, &t);
		return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
	}

	/**
	 * Get system monotonic time in microseconds
	 */
	inline int64_t getMonoTimeUSec() {
		timespec t;
		clock_gettime(CLOCK_MONOTONIC, &t);
		return (int64_t)(t.tv_sec * 1000000000LL + t.tv_nsec) / 1000LL;
	}

	bool addMeasurement(int64_t local_t1_ns, int64_t remote_t2_ns, int64_t local_t3_ns);

@[if 1.5 <= fastrtpsgen_version <= 1.7]@
@[    if ros2_distro]@
	void processTimesyncMsg(@(package)::msg::dds_::Timesync_* msg);

	@(package)::msg::dds_::Timesync_ newTimesyncMsg();
@[    else]@
	void processTimesyncMsg(timesync_* msg);

	timesync_ newTimesyncMsg();
@[    end if]@
@[else]@
@[    if ros2_distro]@
	void processTimesyncMsg(@(package)::msg::Timesync* msg);

	@(package)::msg::Timesync newTimesyncMsg();
@[    else]@
	void processTimesyncMsg(timesync* msg);

	timesync newTimesyncMsg();
@[    end if]@
@[end if]@

        /**
         * @brief Get the time sync offset in nanoseconds
         * @return The offset in nanosecods
         */
	inline int64_t getOffset() { return _offset_ns.load(); }

        /**
         * @brief Sums the time sync offset to the timestamp
         * @param[in,out] timestamp The timestamp to add the offset to
         */
	inline void addOffset(uint64_t& timestamp) { timestamp = (timestamp * 1000LL + _offset_ns.load()) / 1000ULL; }

        /**
         * @brief Substracts the time sync offset to the timestamp
         * @param[in,out] timestamp The timestamp to subtract the offset of
         */
	inline void subtractOffset(uint64_t& timestamp) { timestamp = (timestamp * 1000LL - _offset_ns.load()) / 1000ULL; }

private:
	std::atomic<int64_t> _offset_ns;
	int64_t _skew_ns_per_sync;
	int64_t _num_samples;

	int32_t _request_reset_counter;
	uint8_t _last_msg_seq;
	uint8_t _last_remote_msg_seq;

@[if ros2_distro]@
	Timesync_Publisher _timesync_pub;
	Timesync_Subscriber _timesync_sub;
@[else]@
	timesync_Publisher _timesync_pub;
	timesync_Subscriber _timesync_sub;
@[end if]@

	std::unique_ptr<std::thread> _send_timesync_thread;
	std::atomic<bool> _request_stop{false};

        /**
         * @brief Updates the offset of the time sync filter
         * @param[in] offset The value of the offset to update to
         */
	inline void updateOffset(const uint64_t& offset) { _offset_ns.store(offset, std::memory_order_relaxed); }
};


refactor into variable which contains the entry which gets inserted

@[if os_name == 'ubuntu']@
@{
from itertools import product
}@
@[  if arch in ['amd64', 'i386']]@
@{
archive_commands = []
old_releases_commands = []
for distribution, archive_type in product((os_code_name, os_code_name + '-updates', os_code_name + '-security'), ('deb', 'deb-src')):
    archive_entry = '%s http://archive.ubuntu.com/ubuntu/ %s multiverse' % (archive_type, distribution)
    old_releases_entry = '%s http://old-releases.ubuntu.com/ubuntu/ %s multiverse' % (archive_type, distribution)
    archive_commands.append('echo "%s" >> /etc/apt/sources.list' % archive_entry)
    old_releases_commands.append('echo "%s" >> /etc/apt/sources.list' % old_releases_entry)
}@
RUN grep -q -F -e "deb http://old-releases.ubuntu.com" /etc/apt/sources.list && (@(' && '.join(old_releases_commands))) || (@(' && '.join(archive_commands)))
@[  elif arch in ['armhf', 'armv8']]@
@{
commands = []
for distribution, archive_type in product((os_code_name, os_code_name + '-updates', os_code_name + '-security'), ('deb', 'deb-src')):
    entry = '%s http://ports.ubuntu.com// %s multiverse' % (archive_type, distribution)
    commands.append('echo "%s" >> /etc/apt/sources.list' % entry)
}@
RUN @(' && '.join(commands))
@[  end if]@
@[else if os_name == 'debian']@
# Add contrib and non-free to debian images
# Using httpredir here to match mirror used in osrf image
# (https://github.com/osrf/multiarch-docker-image-generation/blob/d251b9a/build-image.sh#L46)
@{
entry = 'deb http://httpredir.debian.org/debian %s contrib non-free' % os_code_name
}@
RUN echo "@(entry)" | tee -a /etc/apt/sources.list
# Hit cloudfront mirror because of corrupted packages on fastly mirrors (https://github.com/ros-infrastructure/ros_buildfarm/issues/455)
# You can remove this line to target the default mirror or replace this to use the mirror of your preference
RUN sed -i 's/httpredir.debian.org/cloudfront.debian.net/' /etc/apt/sources.list
@[end if]@

@[if os_name == 'ubuntu']@
@{
from itertools import product
}@
@[  if arch in ['amd64', 'i386']]@
@{
archive_commands = []
old_releases_commands = []
for distribution, archive_type in product((os_code_name, os_code_name + '-updates', os_code_name + '-security'), ('deb', 'deb-src')):
    archive_commands.append('echo "%s http://archive.ubuntu.com/ubuntu/ %s multiverse" >> /etc/apt/sources.list' % (archive_type, distribution))
    old_releases_commands.append('echo "%s http://old-releases.ubuntu.com/ubuntu/ %s multiverse" >> /etc/apt/sources.list' % (archive_type, distribution))
}@
RUN grep -q -F -e "deb http://old-releases.ubuntu.com" /etc/apt/sources.list && (@(' && '.join(old_releases_commands))) || (@(' && '.join(archive_commands)))
@[  elif arch in ['armhf', 'armv8']]@
@{
commands = []
for distribution, archive_type in product((os_code_name, os_code_name + '-updates', os_code_name + '-security'), ('deb', 'deb-src')):
    commands.append('echo "%s http://ports.ubuntu.com// %s multiverse" >> /etc/apt/sources.list' % (archive_type, distribution))
}@
RUN @(' && '.join(commands))
@[  end if]@
@[else if os_name == 'debian']@
# Add contrib and non-free to debian images
# Using httpredir here to match mirror used in osrf image
# (https://github.com/osrf/multiarch-docker-image-generation/blob/d251b9a/build-image.sh#L46)
RUN echo deb http://httpredir.debian.org/debian @os_code_name contrib non-free | tee -a /etc/apt/sources.list
# Hit cloudfront mirror because of corrupted packages on fastly mirrors (https://github.com/ros-infrastructure/ros_buildfarm/issues/455)
# You can remove this line to target the default mirror or replace this to use the mirror of your preference
RUN sed -i 's/httpredir.debian.org/cloudfront.debian.net/' /etc/apt/sources.list
@[end if]@


update indentation in templates

update indentation in templates

// generated from ros1_bridge/resource/generated_factories.cpp.em

@###############################################
@#
@# Factory for creating publisher / subscribers
@# based on message names
@#
@# EmPy template for generating generated_factories.cpp
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - ros1_msgs (list of ros1_bridge.Message)
@#    ROS 1 messages
@#  - ros2_msgs (list of ros1_bridge.Message)
@#    ROS 2 messages
@#  - mappings (list of ros1_bridge.Mapping)
@#    Mapping between messages as well as their fields
@###############################################
@
@{
from ros1_bridge import camel_case_to_lower_case_underscore
}@
#include <ros1_bridge/factory.hpp>

// include ROS 1 builtin messages
#include <ros/duration.h>
#include <ros/time.h>

// include ROS 2 builtin messages
#include <builtin_interfaces/msg/duration.hpp>
#include <builtin_interfaces/msg/time.hpp>

// include ROS 1 messages
@[for ros1_msg in ros1_msgs]@
#include <@(ros1_msg.package_name)/@(ros1_msg.message_name).h>
@[end for]@

// include ROS 2 messages
@[for ros2_msg in ros2_msgs]@
#include <@(ros2_msg.package_name)/msg/@(camel_case_to_lower_case_underscore(ros2_msg.message_name)).hpp>
@[end for]@

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory(const std::string & ros1_type_name, const std::string & ros2_type_name)
{
@[if not mappings]@
  (void)ros1_type_name;
  (void)ros2_type_name;
@[end if]@
  // mapping from string to specialized template
@[for m in mappings]@
  if (
    (ros1_type_name == "@(m.ros1_msg.package_name)/@(m.ros1_msg.message_name)" ||
     ros1_type_name == "") &&
    ros2_type_name == "@(m.ros2_msg.package_name)/@(m.ros2_msg.message_name)")
  {
    return std::make_shared<
      Factory<
        @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
        @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
      >
    >();
  }
@[end for]@
  throw std::runtime_error("No template specialization for the pair");
}

// conversion functions for builtin interfaces

template<typename ROS1_T, typename ROS2_T>
void
convert_1_to_2(
  const ROS1_T & ros1_msg,
  ROS2_T & ros2_msg);

template<typename ROS1_T, typename ROS2_T>
void
convert_2_to_1(
  const ROS2_T & ros2_msg,
  ROS1_T & ros1_msg);

template<>
void
convert_1_to_2(
  const ros::Duration & ros1_msg,
  builtin_interfaces::msg::Duration & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Duration & ros2_msg,
  ros::Duration & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

template<>
void
convert_1_to_2(
  const ros::Time & ros1_msg,
  builtin_interfaces::msg::Time & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Time & ros2_msg,
  ros::Time & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

// conversion functions for available interfaces
@[for m in mappings]@

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_1_to_2(
  const @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg,
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg)
{
@[  if not m.fields_1_to_2]@
  (void)ros1_msg;
  (void)ros2_msg;
@[  end if]@
@[  for ros1_field, ros2_field in m.fields_1_to_2.items()]@
@[    if not ros2_field.type.is_array]@
  # convert non-array field
@[      if not ros2_field.type.pkg_name]@
  # convert primitive field
  ros2_msg.@(ros2_field.name) = ros1_msg.@(ros1_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  # convert builtin field
  ros1_bridge::convert_1_to_2(ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      else]@
  # convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_1_to_2(
    ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@[      end if]@
@[    else]@
  # convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  # ensure array size
@[        if ros2_field.type.is_upper_bound]@
  # check boundary
  assert(ros1_msg.@(ros1_field.name).size() <= @(ros2_field.type.array_size));
@[        end if]@
  # dynamic arrays must be resized
  ros2_msg.@(ros2_field.name).resize(ros1_msg.@(ros1_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  # convert primitive array elements
  std::copy(
    ros1_msg.@(ros1_field.name).begin(),
    ros1_msg.@(ros1_field.name).end(),
    ros2_msg.@(ros2_field.name).begin());
@[      else]@
  # copy element wise since the type is different
  {
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    for (
      ;
      ros1_it != ros1_msg.@(ros1_field.name).end() &&
      ros2_it != ros2_msg.@(ros2_field.name).end();
      ++ros1_it, ++ros2_it
    )
    {
      # convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_1_to_2(*ros1_it, *ros2_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_1_to_2(
        *ros1_it, *ros2_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_2_to_1(
  const @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg,
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg)
{
@[  if not m.fields_2_to_1]@
  (void)ros2_msg;
  (void)ros1_msg;
@[  end if]@
@[  for ros2_field, ros1_field in m.fields_2_to_1.items()]@
@[    if not ros2_field.type.is_array]@
  # convert non-array field
@[      if not ros2_field.type.pkg_name]@
  # convert primitive field
  ros1_msg.@(ros1_field.name) = ros2_msg.@(ros2_field.name);
@[      elif ros2_field.type.pkg_name == 'builtin_interfaces']@
  # convert builtin field
  ros1_bridge::convert_2_to_1(ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      else]@
  # convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_2_to_1(
    ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@[      end if]@
@[    else]@
  # convert array field
@[      if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
  # ensure array size
  # dynamic arrays must be resized
  ros1_msg.@(ros1_field.name).resize(ros2_msg.@(ros2_field.name).size());
@[      end if]@
@[      if not ros2_field.type.pkg_name]@
  # convert primitive array elements
  std::copy(
    ros2_msg.@(ros2_field.name).begin(),
    ros2_msg.@(ros2_field.name).end(),
    ros1_msg.@(ros1_field.name).begin());
@[      else]@
  # copy element wise since the type is different
  {
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    for (
      ;
      ros2_it != ros2_msg.@(ros2_field.name).end() &&
      ros1_it != ros1_msg.@(ros1_field.name).end();
      ++ros2_it, ++ros1_it
    )
    {
      # convert sub message element
@[        if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_2_to_1(*ros2_it, *ros1_it);
@[        else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_2_to_1(
        *ros2_it, *ros1_it);
@[        end if]@
    }
  }
@[      end if]@
@[    end if]@
@[  end for]@
}

@[end for]@
}  // namespace ros1_bridge

// generated from ros1_bridge/resource/generated_factories.cpp.em

@###############################################
@#
@# Factory for creating publisher / subscribers
@# based on message names
@#
@# EmPy template for generating generated_factories.cpp
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - ros1_msgs (list of ros1_bridge.Message)
@#    ROS 1 messages
@#  - ros2_msgs (list of ros1_bridge.Message)
@#    ROS 2 messages
@#  - mappings (list of ros1_bridge.Mapping)
@#    Mapping between messages as well as their fields
@###############################################
@
@{
from ros1_bridge import camel_case_to_lower_case_underscore
}@
#include <ros1_bridge/factory.hpp>

// include ROS 1 builtin messages
#include <ros/duration.h>
#include <ros/time.h>

// include ROS 2 builtin messages
#include <builtin_interfaces/msg/duration.hpp>
#include <builtin_interfaces/msg/time.hpp>

// include ROS 1 messages
@[for ros1_msg in ros1_msgs]@
#include <@(ros1_msg.package_name)/@(ros1_msg.message_name).h>
@[end for]@

// include ROS 2 messages
@[for ros2_msg in ros2_msgs]@
#include <@(ros2_msg.package_name)/msg/@(camel_case_to_lower_case_underscore(ros2_msg.message_name)).hpp>
@[end for]@

namespace ros1_bridge
{

std::shared_ptr<FactoryInterface>
get_factory(const std::string & ros1_type_name, const std::string & ros2_type_name)
{
@[if not mappings]@
  (void)ros1_type_name;
  (void)ros2_type_name;
@[end if]@
  // mapping from string to specialized template
@[for m in mappings]@
  if (
    (ros1_type_name == "@(m.ros1_msg.package_name)/@(m.ros1_msg.message_name)" ||
     ros1_type_name == "") &&
    ros2_type_name == "@(m.ros2_msg.package_name)/@(m.ros2_msg.message_name)")
  {
    return std::make_shared<
      Factory<
        @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
        @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
      >
    >();
  }
@[end for]@
  throw std::runtime_error("No template specialization for the pair");
}

// conversion functions for builtin interfaces

template<typename ROS1_T, typename ROS2_T>
void
convert_1_to_2(
  const ROS1_T & ros1_msg,
  ROS2_T & ros2_msg);

template<typename ROS1_T, typename ROS2_T>
void
convert_2_to_1(
  const ROS2_T & ros2_msg,
  ROS1_T & ros1_msg);

template<>
void
convert_1_to_2(
  const ros::Duration & ros1_msg,
  builtin_interfaces::msg::Duration & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Duration & ros2_msg,
  ros::Duration & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

template<>
void
convert_1_to_2(
  const ros::Time & ros1_msg,
  builtin_interfaces::msg::Time & ros2_msg)
{
  ros2_msg.sec = ros1_msg.sec;
  ros2_msg.nanosec = ros1_msg.nsec;
}

template<>
void
convert_2_to_1(
  const builtin_interfaces::msg::Time & ros2_msg,
  ros::Time & ros1_msg)
{
  ros1_msg.sec = ros2_msg.sec;
  ros1_msg.nsec = ros2_msg.nanosec;
}

// conversion functions for available interfaces
@[for m in mappings]@

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_1_to_2(
  const @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg,
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg)
{
@[if not m.fields_1_to_2]@
  (void)ros1_msg;
  (void)ros2_msg;
@[end if]@
@[for ros1_field, ros2_field in m.fields_1_to_2.items()]@
@
@ @[if not ros2_field.type.is_array]@
@ @ @# convert non-array field
@
@ @ @[if not ros2_field.type.pkg_name]@
@ @ @ @# convert primitive field
  ros2_msg.@(ros2_field.name) = ros1_msg.@(ros1_field.name);
@
@ @ @[elif ros2_field.type.pkg_name == 'builtin_interfaces']@
@ @ @ @# convert builtin field
  ros1_bridge::convert_1_to_2(ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@
@ @ @[else]@
@ @ @ @# convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_1_to_2(
    ros1_msg.@(ros1_field.name), ros2_msg.@(ros2_field.name));
@ @ @[end if]@
@
@ @[else]@
@ @ @# convert array field
@
@ @ @[if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
@ @ @ @# ensure array size
@
@ @ @ @[if ros2_field.type.is_upper_bound]@
@ @ @ @ @# check boundary
  assert(ros1_msg.@(ros1_field.name).size() <= @(ros2_field.type.array_size));
@ @ @ @[end if]@
@
@ @ @ @# dynamic arrays must be resized
  ros2_msg.@(ros2_field.name).resize(ros1_msg.@(ros1_field.name).size());
@ @ @[end if]@
@
@ @ @[if not ros2_field.type.pkg_name]@
@ @ @ @# convert primitive array elements
  std::copy(
    ros1_msg.@(ros1_field.name).begin(),
    ros1_msg.@(ros1_field.name).end(),
    ros2_msg.@(ros2_field.name).begin());
@
@ @ @[else]@
@ @ @ @# copy element wise since the type is different
  {
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    for (
      ;
      ros1_it != ros1_msg.@(ros1_field.name).end() &&
      ros2_it != ros2_msg.@(ros2_field.name).end();
      ++ros1_it, ++ros2_it
    )
    {
@ @ @ @# convert sub message element
@ @ @ @[if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_1_to_2(*ros1_it, *ros2_it);
@ @ @ @[else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_1_to_2(
        *ros1_it, *ros2_it);
@ @ @ @[end if]@
    }
  }
@ @ @[end if]@
@ @[end if]@
@[end for]@
}

template<>
void
Factory<
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name),
  @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name)
>::convert_2_to_1(
  const @(m.ros2_msg.package_name)::msg::@(m.ros2_msg.message_name) & ros2_msg,
  @(m.ros1_msg.package_name)::@(m.ros1_msg.message_name) & ros1_msg)
{
@[if not m.fields_2_to_1]@
  (void)ros2_msg;
  (void)ros1_msg;
@[end if]@
@[for ros2_field, ros1_field in m.fields_2_to_1.items()]@
@
@ @[if not ros2_field.type.is_array]@
@ @ @# convert non-array field
@
@ @ @[if not ros2_field.type.pkg_name]@
@ @ @ @# convert primitive field
  ros1_msg.@(ros1_field.name) = ros2_msg.@(ros2_field.name);
@
@ @ @[elif ros2_field.type.pkg_name == 'builtin_interfaces']@
@ @ @ @# convert builtin field
  ros1_bridge::convert_2_to_1(ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@
@ @ @[else]@
@ @ @ @# convert sub message field
  Factory<
    @(ros1_field.pkg_name)::@(ros1_field.msg_name),
    @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
  >::convert_2_to_1(
    ros2_msg.@(ros2_field.name), ros1_msg.@(ros1_field.name));
@ @ @[end if]@
@
@ @[else]@
@ @ @# convert array field
@
@ @ @[if not ros2_field.type.array_size or ros2_field.type.is_upper_bound]@
@ @ @ @# ensure array size
@
@ @ @ @# dynamic arrays must be resized
  ros1_msg.@(ros1_field.name).resize(ros2_msg.@(ros2_field.name).size());
@ @ @[end if]@
@
@ @ @[if not ros2_field.type.pkg_name]@
@ @ @ @# convert primitive array elements
  std::copy(
    ros2_msg.@(ros2_field.name).begin(),
    ros2_msg.@(ros2_field.name).end(),
    ros1_msg.@(ros1_field.name).begin());
@
@ @ @[else]@
@ @ @ @# copy element wise since the type is different
  {
    auto ros2_it = ros2_msg.@(ros2_field.name).begin();
    auto ros1_it = ros1_msg.@(ros1_field.name).begin();
    for (
      ;
      ros2_it != ros2_msg.@(ros2_field.name).end() &&
      ros1_it != ros1_msg.@(ros1_field.name).end();
      ++ros2_it, ++ros1_it
    )
    {
@ @ @ @# convert sub message element
@ @ @ @[if ros2_field.type.pkg_name == 'builtin_interfaces']@
      ros1_bridge::convert_2_to_1(*ros2_it, *ros1_it);
@ @ @ @[else]@
      Factory<
        @(ros1_field.pkg_name)::@(ros1_field.msg_name),
        @(ros2_field.type.pkg_name)::msg::@(ros2_field.type.type)
      >::convert_2_to_1(
        *ros2_it, *ros1_it);
@ @ @ @[end if]@
    }
  }
@ @ @[end if]@
@ @[end if]@
@[end for]@
}

@[end for]@
}  // namespace ros1_bridge


need python-empy to be building

need python-empy to be building

Source: catkin
Section: misc
Priority: extra
Maintainer: Troy Straszheim <straszheim@@willowgarage.com>
Build-Depends: debhelper (>= 7), cmake, gcc, make, python-empy
Homepage: http://www.ros.org

Package: catkin
Architecture: all
Depends: ${misc:Depends} python-empy, cmake, make
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
X-ROS-Pkg-Name: catkin
X-ROS-Pkg-Depends:
X-ROS-System-Depends:

Source: catkin
Section: misc
Priority: extra
Maintainer: Troy Straszheim <straszheim@@willowgarage.com>
Build-Depends: debhelper (>= 7), cmake, gcc, make
Homepage: http://www.ros.org

Package: catkin
Architecture: all
Depends: ${misc:Depends} python-empy, cmake, make
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
X-ROS-Pkg-Name: catkin
X-ROS-Pkg-Depends:
X-ROS-System-Depends:


Old mknod.em deleted

Old mknod.em deleted

$_MODS += mknod
$_SRCS-mknod += mknod.c
$_DEPS-mknod += embox.fs.core

$_BRIEF-mknod = Create special file

define $_DETAILS-mknod
	NAME
		mknode - create special file
	SYNOPSIS
		mknod NAME
	DESCRIPTION
		create virtual node in file system
	AUTHORS
		Anton Bondarev
endef


[GladiatorTool] backup

[GladiatorTool] backup

macro _ReplaceInBufRegex( hbuf, oldPattern, newPattern )
{
  lnStart         = 0;
  lnLim           = GetBufLineCount( hbuf );
  fMatchCase      = 0;
  fRegExp         = 1;
  fWholeWordsOnly = 0;
  fConfirm        = 1;

  ReplaceInBuf( hbuf, oldPattern, newPattern, lnStart, lnLim,
                fMatchCase, fRegExp, fWholeWordsOnly, fConfirm );
}

macro RefactorGetData( )
{
  hbuf = GetCurrentBuf( );
  sel  = GetBufSelText( hbuf );

  if ( sel == nil )
  {
    return;
  }

  oldPattern = "\\(.*=.*\\)\\(@sel@\\)\\(.*;.*\\)";
  newPattern = "\\1\\Get@sel@()\\3";

  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  AppendBufLine( hbuf, "void Get@sel@( void )" );
  AppendBufLine( hbuf, "{" );
  AppendBufLine( hbuf, "  return @sel@;" );
  AppendBufLine( hbuf, "}" );
}

macro RefactorSetData( )
{
  hbuf = GetCurrentBuf( );
  sel  = GetBufSelText( hbuf );

  if ( sel == nil )
  {
    return;
  }

  oldPattern = "\\(\\w*@sel@\\w*=\\)\\(.*\\)\\(;\\)";
  newPattern = "\\Set@sel@(\\2\\)";

  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  AppendBufLine( hbuf, "void Set@sel@( var )" );
  AppendBufLine( hbuf, "{" );
  AppendBufLine( hbuf, "  @sel@ = var;" );
  AppendBufLine( hbuf, "}" );
}

macro RefactorExtractMethod( )
{
  hbuf = GetCurrentBuf( );
  hwnd = GetCurrentWnd( );
  sel  = GetWndSel( hwnd );

  // Create extracted fucntion
  AppendBufLine( hbuf, "void extractedfunction( void )" );
  AppendBufLine( hbuf, "{" );
  iLine = sel.lnFirst;
  while ( iLine <= sel.lnLast )
  {
    szLine = GetBufLine( hbuf, iLine );
    AppendBufLine( hbuf, szLine );
    iLine = iLine + 1;
  }
  AppendBufLine( hbuf, "}" );

  iLine = sel.lnFirst; // Save line number

  cut; // Delete origin code block

  // Call extracted function
  InsBufLine( hbuf, iLine, "extractedfunction( );" );
}

macro RefactorMisraConstU( )
{
  hbuf = GetCurrentBuf( );

  // Constant like 0xff, 0x10, white space at the end
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+\\)\\([\\w;,]\\)";
  newPattern = "\\1\\u\\2\\";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 0xff, 0x10, white space at the end
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+\\)\\w";
  newPattern = "\\1\\u\\s";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 0xff, 0x10, and at the end of the line
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+$\\)";
  // Add u at the end
  newPattern = "\\1\\u";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 10, 356, ; or , at the end
  oldPattern = "\\(\\w[0-9]+\\)\\([;,]\\)";
  newPattern = "\\1\\u\\2\\";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant white space at the end
  oldPattern = "\\(\\w[0-9]+\\)\\w";
  newPattern = "\\1\\u\\s";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant at the end of the line
  oldPattern = "\\(\\w[0-9]+$\\)";
  // Add u at the end
  newPattern = "\\1\\u";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );
}

// Add Bracket for define, for example
// Before:  #define XXX YYY ZZZ
// After :  #define XXX ( YYY ZZZ )
macro RefactorDefineAddBracket( )
{
  hbuf = GetCurrentBuf( );

  oldPattern = "\\(\\#define\\w+.+\\w+\\)\\(.+[^)]$\\)";
  newPattern = "\\1\\( \\2\\ )";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );
}

macro _ReplaceInBufRegex( hbuf, oldPattern, newPattern )
{
  lnStart         = 0;
  lnLim           = GetBufLineCount( hbuf );
  fMatchCase      = 0;
  fRegExp         = 1;
  fWholeWordsOnly = 0;
  fConfirm        = 1;

  ReplaceInBuf( hbuf, oldPattern, newPattern, lnStart, lnLim,
                fMatchCase, fRegExp, fWholeWordsOnly, fConfirm );
}

macro RefactorGetData( )
{
  hbuf = GetCurrentBuf( );
  sel  = GetBufSelText( hbuf );

  if ( sel == nil )
  {
    return;
  }

  oldPattern = "\\(.*=.*\\)\\(@sel@\\)\\(.*;.*\\)";
  newPattern = "\\1\\Get@sel@()\\3";

  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  AppendBufLine( hbuf, "void Get@sel@( void )" );
  AppendBufLine( hbuf, "{" );
  AppendBufLine( hbuf, "  return @sel@;" );
  AppendBufLine( hbuf, "}" );
}

macro RefactorSetData( )
{
  hbuf = GetCurrentBuf( );
  sel  = GetBufSelText( hbuf );

  if ( sel == nil )
  {
    return;
  }

  oldPattern = "\\(\\w*@sel@\\w*=\\)\\(.*\\)\\(;\\)";
  newPattern = "\\Set@sel@(\\2\\);"

               _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  AppendBufLine( hbuf, "void Set@sel@( var )" );
  AppendBufLine( hbuf, "{" );
  AppendBufLine( hbuf, "  @sel@ = var;" );
  AppendBufLine( hbuf, "}" );
}

macro RefactorExtractMethod( )
{
  hbuf = GetCurrentBuf( );
  hwnd = GetCurrentWnd( );
  sel  = GetWndSel( hwnd );

  // Create extracted fucntion
  AppendBufLine( hbuf, "void extractedfunction( void )" );
  AppendBufLine( hbuf, "{" );
  iLine = sel.lnFirst;
  while ( iLine <= sel.lnLast )
  {
    szLine = GetBufLine( hbuf, iLine );
    AppendBufLine( hbuf, szLine );
    iLine = iLine + 1;
  }
  AppendBufLine( hbuf, "}" );

  iLine = sel.lnFirst; // Save line number

  cut;      // Delete origin code block

  // Call extracted function
  InsBufLine( hbuf, iLine, "extractedfunction( );" );
}

macro RefactorMisraConstU( )
{
  hbuf = GetCurrentBuf( );

  // Constant like 0xff, 0x10, white space at the end
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+\\)\\([\\w;,]\\)";
  newPattern = "\\1\\u\\2\\";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 0xff, 0x10, white space at the end
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+\\)\\w";
  newPattern = "\\1\\u\\s";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 0xff, 0x10, and at the end of the line
  oldPattern = "\\(\\w0[xX][0-9a-fA-F]+$\\)";
  // Add u at the end
  newPattern = "\\1\\u";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant like 10, 356, ; or , at the end
  oldPattern = "\\(\\w[0-9]+\\)\\([;,]\\)";
  newPattern = "\\1\\u\\2\\";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant white space at the end
  oldPattern = "\\(\\w[0-9]+\\)\\w";
  newPattern = "\\1\\u\\s";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );

  // Constant at the end of the line
  oldPattern = "\\(\\w[0-9]+$\\)";
  // Add u at the end
  newPattern = "\\1\\u";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );
}

// Add Bracket for define, for example
// Before:  #define XXX YYY ZZZ
// After :  #define XXX ( YYY ZZZ )
macro RefactorDefineAddBracket( )
{
  hbuf = GetCurrentBuf( );

  oldPattern = "\\(\\#define\\w+.+\\w+\\)\\(.+[^)]$\\)";
  newPattern = "\\1\\( \\2\\ )";
  _ReplaceInBufRegex( hbuf, oldPattern, newPattern );
}


fix recursion issue

fix recursion issue

#!/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 --buildsystem=cmake
export CMAKE_PREFIX_PATH=@(INSTALL_PREFIX)
# TODO: remove the LDFLAGS override.  It's here to avoid esoteric problems
# of this sort:
#  https://code.ros.org/trac/ros/ticket/2977
#  https://code.ros.org/trac/ros/ticket/3842
export LDFLAGS=
export PKG_CONFIG_PATH=@(INSTALL_PREFIX)/lib/pkgconfig

%:
	dh  $@@

#
#  The CATKIN=YES is needed to make it possible for
#  ROS packages to build under rosmake and catkin
#
override_dh_auto_configure:
	dh_auto_configure -- \
		-DCMAKE_INSTALL_PREFIX="@(INSTALL_PREFIX)" \
		-DCMAKE_PREFIX_PATH="@(INSTALL_PREFIX)"

override_dh_auto_test:
	echo -- Running tests. Even if one of them fails the build is not canceled.
	dh_auto_test || true

override_dh_shlibdeps:
	dh_shlibdeps -l$(CURDIR)/debian/@(Package)/@(INSTALL_PREFIX)/lib/

#!/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 --buildsystem=cmake
export CMAKE_PREFIX_PATH=@(INSTALL_PREFIX)
# TODO: remove the LDFLAGS override.  It's here to avoid esoteric problems
# of this sort:
#  https://code.ros.org/trac/ros/ticket/2977
#  https://code.ros.org/trac/ros/ticket/3842
export LDFLAGS=
export PKG_CONFIG_PATH=@(INSTALL_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)

%:
	dh  $@@

#
#  The CATKIN=YES is needed to make it possible for
#  ROS packages to build under rosmake and catkin
#
override_dh_auto_configure:
	dh_auto_configure -- \
		-DCMAKE_INSTALL_PREFIX="@(INSTALL_PREFIX)" \
		-DCMAKE_PREFIX_PATH="@(INSTALL_PREFIX)"

override_dh_auto_test:
	echo -- Running tests. Even if one of them fails the build is not canceled.
	dh_auto_test || true

override_dh_shlibdeps:
	dh_shlibdeps -l$(CURDIR)/debian/@(Package)/@(INSTALL_PREFIX)/lib/