예제 #1
0
    def __init__(self, stack_widget, on_name_chosen_func):
        self._stack_widget = stack_widget
        self._on_name_chosen_func = on_name_chosen_func

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        title.text = "Save project as"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        options_layout = widget.HStackedLayoutWidget()
        layout.add_child(options_layout)

        name_title = widget.TextWidget()
        options_layout.add_child(name_title, horizontal_placement = widget.HorizontalPlacement.RIGHT)
        name_title.text = "Name:"
        name_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        name_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        options_layout.add_padding(points(4.0))

        self._name = widget.InputWidget()
        options_layout.add_child(self._name)

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)
        buttons_layout.add_padding(0.0, weight = 1.0)

        cancel_button = widget.TextButtonWidget()
        buttons_layout.add_child(cancel_button)
        cancel_button.text = "Cancel"
        cancel_button.action_func = self._cancel

        buttons_layout.add_padding(points(4.0))

        save_button = widget.TextButtonWidget()
        buttons_layout.add_child(save_button)
        save_button.text = "Save"
        save_button.action_func = self._save

        self._destroy_func = modal_dialog.show_modal_dialog(stack_widget, layout)
예제 #2
0
    def __init__(self, on_click_func):
        super().__init__()
        self.on_click_func = on_click_func
        self.enabled = True

        self.desired_width = _get_measure_width(None)
        self.desired_height = _get_track_height(
        )  # Measures line up with tracks

        self.background = widget.RectangleWidget()
        self.background.desired_width = self.desired_width
        self.background.desired_height = self.desired_height
        self.background.color.value = _get_measure_color(None)
        self.background.border_thickness.value = points(1.0)
        self.background.border_color.value = constants.Color.BLACK
        self.background.radius.value = points(4.0)
        self.add_child(self.background)

        self.name = widget.TextWidget()
        self.name.text = ""
        self.name.x.value = self.desired_width * 0.5
        self.name.y.value = self.desired_height * 0.5
        self.name.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        self.name.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        self.add_child(self.name)
예제 #3
0
    def __init__(self, category, clip, is_selected, on_click_func,
                 on_double_click_func):
        super().__init__()
        self.category = category
        self.clip = clip
        self.on_click_func = on_click_func
        self.on_double_click_func = on_double_click_func
        self.enabled = True

        self.desired_width = inches(1.5)
        self.desired_height = inches(1.0)

        self.background = widget.RectangleWidget()
        self.background.desired_width = self.desired_width
        self.background.desired_height = self.desired_height
        self.background.color.value = constants.rgba255(*self.category.color)
        self.background.border_thickness.value = points(1.0)
        self.background.border_color.value = self.SELECTED_COLOR if is_selected else self.UNSELECTED_COLOR
        self.background.radius.value = points(4.0)
        self.add_child(self.background)

        self.name = widget.TextWidget()
        self.name.text = self.clip.name
        self.name.x.value = self.desired_width * 0.5
        self.name.y.value = self.desired_height * 0.5
        self.name.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        self.name.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        self.add_child(self.name)
예제 #4
0
def show_simple_modal_dialog(stack_widget, title, text, buttons,
                             on_closed_func):
    layout = widget.VStackedLayoutWidget()

    title_widget = widget.TextWidget()
    layout.add_child(title_widget)
    title_widget.text = title
    title_widget.size.value = points(20.0)
    title_widget.horizontal_alignment = drawing.HorizontalAlignment.CENTER
    title_widget.vertical_alignment = drawing.VerticalAlignment.MIDDLE

    layout.add_padding(points(12.0))

    text_widget = widget.TextWidget()
    layout.add_child(text_widget)
    text_widget.text = text
    text_widget.horizontal_alignment = drawing.HorizontalAlignment.CENTER
    text_widget.vertical_alignment = drawing.VerticalAlignment.MIDDLE

    layout.add_padding(points(12.0))

    buttons_layout = widget.HStackedLayoutWidget()
    layout.add_child(buttons_layout)
    buttons_layout.add_padding(0.0, weight=1.0)

    class Context:
        def __init__(self):
            self.destroy_func = None

        def button_pressed(self, i):
            self.destroy_func()
            if on_closed_func is not None:
                on_closed_func(i)

    context = Context()
    for i, button_text in enumerate(buttons):
        button_widget = widget.TextButtonWidget()
        if i > 0:
            buttons_layout.add_padding(points(4.0))
        buttons_layout.add_child(button_widget)
        button_widget.text = button_text
        button_widget.action_func = lambda i=i: context.button_pressed(i)

    context.destroy_func = show_modal_dialog(stack_widget, layout)
예제 #5
0
    def __init__(self, stack_widget, on_project_selected_func):
        self._stack_widget = stack_widget
        self._on_project_selected_func = on_project_selected_func

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        title.text = "Load project"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        # $TODO replace this with a list widget (which does not currently exist!)
        self._name = widget.InputWidget()
        layout.add_child(self._name)

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)
        buttons_layout.add_padding(0.0, weight=1.0)

        cancel_button = widget.TextButtonWidget()
        buttons_layout.add_child(cancel_button)
        cancel_button.text = "Cancel"
        cancel_button.action_func = self._cancel

        buttons_layout.add_padding(points(4.0))

        load_button = widget.TextButtonWidget()
        buttons_layout.add_child(load_button)
        load_button.text = "Load"
        load_button.action_func = self._load

        self._destroy_func = modal_dialog.show_modal_dialog(
            stack_widget, layout)
예제 #6
0
    def __init__(self, stack_widget):
        self._stack_widget = stack_widget

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        title.text = "Settings"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        options_layout = widget.GridLayoutWidget()
        layout.add_child(options_layout)

        options_layout.set_column_size(1, points(4.0))

        input_device_title = widget.TextWidget()
        options_layout.add_child(
            0,
            0,
            input_device_title,
            horizontal_placement=widget.HorizontalPlacement.RIGHT)
        input_device_title.text = "Input device:"
        input_device_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        input_device_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        input_device_count = engine.get_input_device_count()
        self._input_device = widget.DropdownWidget()
        options_layout.add_child(0, 2, self._input_device)
        self._input_device.set_options([(i, engine.get_input_device_name(i))
                                        for i in range(input_device_count)])
        self._input_device.selected_option_index = settings.get(
        ).input_device_index

        options_layout.set_row_size(1, points(12.0))

        output_device_title = widget.TextWidget()
        options_layout.add_child(
            2,
            0,
            output_device_title,
            horizontal_placement=widget.HorizontalPlacement.RIGHT)
        output_device_title.text = "Output device:"
        output_device_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        output_device_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        output_device_count = engine.get_output_device_count()
        self._output_device = widget.DropdownWidget()
        options_layout.add_child(2, 2, self._output_device)
        self._output_device.set_options([(i, engine.get_output_device_name(i))
                                         for i in range(output_device_count)])
        self._output_device.selected_option_index = settings.get(
        ).output_device_index

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)
        buttons_layout.add_padding(0.0, weight=1.0)

        cancel_button = widget.TextButtonWidget()
        buttons_layout.add_child(cancel_button)
        cancel_button.text = "Cancel"
        cancel_button.action_func = self._cancel

        buttons_layout.add_padding(points(4.0))

        ok_button = widget.TextButtonWidget()
        buttons_layout.add_child(ok_button)
        ok_button.text = "OK"
        ok_button.action_func = self._accept

        self._destroy_func = modal_dialog.show_modal_dialog(
            stack_widget, layout)
예제 #7
0
    def __init__(self, stack_widget, on_project_created_func):
        self._stack_widget = stack_widget
        self._on_project_created_func = on_project_created_func

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        title.text = "New project"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        options_layout = widget.GridLayoutWidget()
        layout.add_child(options_layout)

        options_layout.set_column_size(1, points(4.0))

        name_title = widget.TextWidget()
        options_layout.add_child(0, 0, name_title, horizontal_placement = widget.HorizontalPlacement.RIGHT)
        name_title.text = "Name:"
        name_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        name_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        self._name = widget.InputWidget()
        options_layout.add_child(0, 2, self._name)

        options_layout.set_row_size(1, points(12.0))

        sample_rate_title = widget.TextWidget()
        options_layout.add_child(2, 0, sample_rate_title, horizontal_placement = widget.HorizontalPlacement.RIGHT)
        sample_rate_title.text = "Sample rate:"
        sample_rate_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        sample_rate_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        self._sample_rate = widget.DropdownWidget()
        self._sample_rate.set_options(_SAMPLE_RATES)
        self._sample_rate.selected_option_index = 0
        options_layout.add_child(2, 2, self._sample_rate)

        options_layout.set_row_size(3, points(12.0))

        beats_per_minute_title = widget.TextWidget()
        options_layout.add_child(4, 0, beats_per_minute_title, horizontal_placement = widget.HorizontalPlacement.RIGHT)
        beats_per_minute_title.text = "Beats per minute:"
        beats_per_minute_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        beats_per_minute_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        self._beats_per_minute = widget.SpinnerWidget()
        self._beats_per_minute.min_value = 40.0
        self._beats_per_minute.max_value = 160.0
        self._beats_per_minute.value = 60.0
        self._beats_per_minute.decimals = 1
        options_layout.add_child(4, 2, self._beats_per_minute)

        options_layout.set_row_size(5, points(12.0))

        beats_per_measure_title = widget.TextWidget()
        options_layout.add_child(6, 0, beats_per_measure_title, horizontal_placement = widget.HorizontalPlacement.RIGHT)
        beats_per_measure_title.text = "Beats per measure:"
        beats_per_measure_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        beats_per_measure_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        self._beats_per_measure = widget.SpinnerWidget()
        self._beats_per_measure.min_value = 2.0
        self._beats_per_measure.max_value = 8.0
        self._beats_per_measure.value = 4.0
        self._beats_per_measure.decimals = 0
        options_layout.add_child(6, 2, self._beats_per_measure)

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)
        buttons_layout.add_padding(0.0, weight = 1.0)

        cancel_button = widget.TextButtonWidget()
        buttons_layout.add_child(cancel_button)
        cancel_button.text = "Cancel"
        cancel_button.action_func = self._cancel

        buttons_layout.add_padding(points(4.0))

        create_button = widget.TextButtonWidget()
        buttons_layout.add_child(create_button)
        create_button.text = "Create"
        create_button.action_func = self._create

        self._destroy_func = modal_dialog.show_modal_dialog(stack_widget, layout)
예제 #8
0
    def __init__(self, stack_widget, category, on_accept_func, on_delete_func):
        self._stack_widget = stack_widget
        self._on_accept_func = on_accept_func
        self._on_delete_func = on_delete_func

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        if category is None:
            title.text = "Create category"
        else:
            title.text = "Edit category"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        options_layout = widget.GridLayoutWidget()
        layout.add_child(options_layout)

        options_layout.set_column_size(1, points(4.0))

        name_title = widget.TextWidget()
        options_layout.add_child(
            0,
            0,
            name_title,
            horizontal_placement=widget.HorizontalPlacement.RIGHT)
        name_title.text = "Name:"
        name_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        name_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        name_gain_layout = widget.HStackedLayoutWidget()
        options_layout.add_child(0, 2, name_gain_layout)

        self._name = widget.InputWidget()
        name_gain_layout.add_child(self._name)
        if category is not None:
            self._name.text = category.name

        name_gain_layout.add_padding(points(4.0))

        self._gain_spinner = widget.SpinnerWidget()
        name_gain_layout.add_child(self._gain_spinner)
        self._gain_spinner.min_value = 0.0
        self._gain_spinner.max_value = 1.0
        self._gain_spinner.value = 1.0 if category is None else category.gain
        self._gain_spinner.decimals = 2

        options_layout.set_row_size(1, points(12.0))

        color_title = widget.TextWidget()
        options_layout.add_child(
            2,
            0,
            color_title,
            horizontal_placement=widget.HorizontalPlacement.RIGHT)
        color_title.text = "Color:"
        color_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        color_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        selected_color = category.color if category is not None else project.CATEGORY_COLORS[
            0]
        self._color_picker = ColorPickerWidget(4, project.CATEGORY_COLORS,
                                               selected_color)
        options_layout.add_child(2, 2, self._color_picker)

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)

        if category is not None:
            delete_button = widget.IconButtonWidget()
            buttons_layout.add_child(delete_button)
            delete_button.icon_name = "delete"
            delete_button.action_func = self._delete

        buttons_layout.add_padding(points(4.0), weight=1.0)

        accept_button = widget.IconButtonWidget()
        buttons_layout.add_child(accept_button)
        accept_button.color = constants.Ui.ACCEPT_BUTTON_COLOR
        accept_button.icon_name = "accept"
        accept_button.action_func = self._accept

        buttons_layout.add_padding(points(4.0))

        reject_button = widget.IconButtonWidget()
        buttons_layout.add_child(reject_button)
        reject_button.color = constants.Ui.REJECT_BUTTON_COLOR
        reject_button.icon_name = "reject"
        reject_button.action_func = self._reject

        self._destroy_func = modal_dialog.show_modal_dialog(
            stack_widget, layout)
예제 #9
0
    def __init__(self, stack_widget, project, clip, on_accept_func,
                 on_delete_func):
        self._stack_widget = stack_widget
        self._project = project
        self._clip = clip
        self._on_accept_func = on_accept_func
        self._on_delete_func = on_delete_func

        layout = widget.VStackedLayoutWidget()

        title = widget.TextWidget()
        if clip is None:
            title.text = "Record clip"
        else:
            title.text = "Edit clip"
        title.size.value = points(20.0)
        title.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        title.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        layout.add_child(title)

        layout.add_padding(points(12.0))

        name_gain_layout = widget.HStackedLayoutWidget()
        layout.add_child(
            name_gain_layout,
            horizontal_placement=widget.HorizontalPlacement.CENTER)

        name_title = widget.TextWidget()
        name_gain_layout.add_child(
            name_title, horizontal_placement=widget.HorizontalPlacement.RIGHT)
        name_title.text = "Name:"
        name_title.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        name_title.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        name_gain_layout.add_padding(points(4.0))

        self._name = widget.InputWidget()
        name_gain_layout.add_child(self._name)
        if clip is not None:
            self._name.text = clip.name

        name_gain_layout.add_padding(points(4.0))

        self._gain_spinner = widget.SpinnerWidget()
        name_gain_layout.add_child(self._gain_spinner)
        self._gain_spinner.min_value = 0.0
        self._gain_spinner.max_value = 1.0
        self._gain_spinner.value = 1.0 if clip is None else clip.gain
        self._gain_spinner.decimals = 2

        layout.add_padding(points(12.0))

        self._time_bar = time_bar.TimeBarWidget()
        layout.add_child(
            self._time_bar,
            horizontal_placement=widget.HorizontalPlacement.CENTER)
        self._time_bar.desired_width = inches(
            8.0) - _get_waveform_border_thickness() * 2.0
        self._time_bar.desired_height = points(20.0)
        self._time_bar.on_sample_changed_func = self._on_time_bar_sample_changed

        layout.add_padding(points(4.0))

        self._waveform_viewer = WaveformWidget()
        layout.add_child(self._waveform_viewer)
        self._waveform_viewer.desired_width = inches(8.0)
        self._waveform_viewer.desired_height = inches(2.0)
        if clip is None:
            self._waveform_viewer.set_waveform_samples([0.0])
            self._waveform_viewer.sample_count = 0
            self._waveform_viewer.enabled = False
        else:
            self._waveform_viewer.set_waveform_samples(
                engine.get_clip_samples(clip.engine_clip,
                                        _MAX_WAVEFORM_SAMPLES))
            self._waveform_viewer.sample_count = clip.sample_count
            self._waveform_viewer.start_sample_index = clip.start_sample_index
            self._waveform_viewer.end_sample_index = clip.end_sample_index

        layout.add_padding(points(12.0))

        measures_layout = widget.HStackedLayoutWidget()
        layout.add_child(measures_layout)

        self._intro_checkbox = widget.CheckboxWidget()
        measures_layout.add_child(
            self._intro_checkbox,
            vertical_placement=widget.VerticalPlacement.MIDDLE)
        self._intro_checkbox.set_checked(
            True if self._clip is None else self._clip.has_intro, False)
        self._intro_checkbox.action_func = self._update_measures_text

        measures_layout.add_padding(points(4.0))

        intro_text = widget.TextWidget()
        measures_layout.add_child(
            intro_text,
            horizontal_placement=widget.HorizontalPlacement.LEFT,
            vertical_placement=widget.VerticalPlacement.MIDDLE)
        intro_text.text = "Intro measure"
        intro_text.horizontal_alignment = drawing.HorizontalAlignment.LEFT
        intro_text.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        self._measures_text = widget.TextWidget()
        measures_layout.add_child(
            self._measures_text,
            weight=1.0,
            vertical_placement=widget.VerticalPlacement.MIDDLE)
        self._measures_text.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        self._measures_text.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        outro_text = widget.TextWidget()
        measures_layout.add_child(
            outro_text,
            horizontal_placement=widget.HorizontalPlacement.RIGHT,
            vertical_placement=widget.VerticalPlacement.MIDDLE)
        outro_text.text = "Outro measure"
        outro_text.horizontal_alignment = drawing.HorizontalAlignment.RIGHT
        outro_text.vertical_alignment = drawing.VerticalAlignment.MIDDLE

        measures_layout.add_padding(points(4.0))

        self._outro_checkbox = widget.CheckboxWidget()
        measures_layout.add_child(
            self._outro_checkbox,
            vertical_placement=widget.VerticalPlacement.MIDDLE)
        self._outro_checkbox.set_checked(
            True if self._clip is None else self._clip.has_outro, False)
        self._outro_checkbox.action_func = self._update_measures_text

        layout.add_padding(points(12.0))

        buttons_layout = widget.HStackedLayoutWidget()
        layout.add_child(buttons_layout)

        self._record_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._record_button)
        self._record_button.color = (0.75, 0.0, 0.0, 1.0)
        self._record_button.icon_name = "record"
        self._record_button.action_func = self._record

        buttons_layout.add_padding(points(4.0))

        self._play_pause_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._play_pause_button)
        self._play_pause_button.icon_name = "play"
        self._play_pause_button.action_func = self._play_pause
        self._play_pause_button.set_enabled(clip is not None, False)

        buttons_layout.add_padding(points(4.0))

        self._stop_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._stop_button)
        self._stop_button.icon_name = "stop"
        self._stop_button.action_func = self._stop
        self._stop_button.set_enabled(clip is not None, False)

        buttons_layout.add_padding(points(4.0))

        self._metronome_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._metronome_button)
        self._metronome_button.icon_name = self._get_metronome_icon()
        self._metronome_button.action_func = self._toggle_metronome

        if clip is not None:
            buttons_layout.add_padding(points(4.0))

            self._delete_button = widget.IconButtonWidget()
            buttons_layout.add_child(self._delete_button)
            self._delete_button.icon_name = "delete"
            self._delete_button.action_func = self._delete

        buttons_layout.add_padding(points(4.0), weight=1.0)

        self._accept_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._accept_button)
        self._accept_button.color = constants.Ui.ACCEPT_BUTTON_COLOR
        self._accept_button.icon_name = "accept"
        self._accept_button.action_func = self._accept

        buttons_layout.add_padding(points(4.0))

        self._reject_button = widget.IconButtonWidget()
        buttons_layout.add_child(self._reject_button)
        self._reject_button.color = constants.Ui.REJECT_BUTTON_COLOR
        self._reject_button.icon_name = "reject"
        self._reject_button.action_func = self._reject

        self._engine_clip = None
        self._is_recording = False
        self._recording_updater = None
        self._is_playing = False
        self._playback_updater = None
        self._last_clicked_sample_index = None

        self._update_time_bar()
        self._update_measures_text()

        self._destroy_func = modal_dialog.show_modal_dialog(
            stack_widget, layout)
예제 #10
0
    def __init__(self, track, on_double_click_func, on_mute_func,
                 on_solo_func):
        super().__init__()
        self.track = track
        self.on_double_click_func = on_double_click_func
        self._enabled = True

        self.desired_width = _get_track_width()
        self.desired_height = _get_track_height()

        self.background = widget.RectangleWidget()
        self.background.desired_width = self.desired_width
        self.background.desired_height = self.desired_height
        self.background.color.value = constants.Ui.TRACK_COLOR
        self.background.border_thickness.value = points(4.0)
        self.background.border_color.value = constants.darken_color(
            constants.Ui.TRACK_COLOR, 0.75)
        self.background.radius.value = points(4.0)
        self.add_child(self.background)

        name_controls_layout = widget.HStackedLayoutWidget()
        name_controls_layout.desired_width = self.desired_width
        name_controls_layout.desired_height = self.desired_height
        name_controls_layout.margin = points(8.0)
        self.add_child(name_controls_layout)

        self.name = widget.TextWidget()
        self.name.text = self.track.name
        self.name.horizontal_alignment = drawing.HorizontalAlignment.CENTER
        self.name.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        name_controls_layout.add_child(
            self.name,
            weight=1.0,
            horizontal_placement=widget.HorizontalPlacement.CENTER,
            vertical_placement=widget.VerticalPlacement.MIDDLE)

        name_controls_layout.add_padding(points(4.0))

        controls_layout = widget.GridLayoutWidget()
        controls_layout.set_row_size(1, points(4.0))
        controls_layout.set_column_size(1, points(4.0))
        name_controls_layout.add_child(
            controls_layout,
            vertical_placement=widget.VerticalPlacement.MIDDLE)

        self.muted = widget.CheckboxWidget()
        self.muted.set_checked(track.muted, animate=False)
        self.muted.action_func = on_mute_func
        controls_layout.add_child(0, 0, self.muted)

        muted_text = widget.TextWidget()
        muted_text.text = "M"
        muted_text.horizontal_alignment = drawing.HorizontalAlignment.LEFT
        muted_text.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        controls_layout.add_child(
            0,
            2,
            muted_text,
            horizontal_placement=widget.HorizontalPlacement.LEFT)

        self.soloed = widget.CheckboxWidget()
        self.soloed.set_checked(track.soloed, animate=False)
        self.soloed.action_func = on_solo_func
        controls_layout.add_child(2, 0, self.soloed)

        soloed_text = widget.TextWidget()
        soloed_text.text = "S"
        soloed_text.horizontal_alignment = drawing.HorizontalAlignment.LEFT
        soloed_text.vertical_alignment = drawing.VerticalAlignment.MIDDLE
        controls_layout.add_child(
            2,
            2,
            soloed_text,
            horizontal_placement=widget.HorizontalPlacement.LEFT)