/*
* menu.h
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/

#ifndef __menu
#define __menu

#define MENU uis.main_menu
#define MENUP &MENU

#include "button.h"
#include "checkbutton.h"
#include "ui.h"
#include "label.h"
#include "separator.h"
#include "arrow_button.h"
#include "spinner.h"
#include "spinner2.h"
#include "options_list.h"
#include "label_field.h"
#include "slider.h"
#include "tap_bpm.h"
#include "plus_button.h"
#include "minus_button.h"
#include "curve_listener.h"
#include "item_list.h"
#include "instrument.h"
#include "drone.h"
#include "drawrrow.h"

#include <map>
#include <vector>
#include <string>

#define TOGGLEMENU MENU.toggle ();

struct ball;

DECL_CLICK_LISTENER (pan_zoom_listener)
DECL_CLICK_LISTENER (snap_listener)
DECL_FIELD_LISTENER (gater_bpm_listener)
DECL_FIELD_LISTENER (voice_volume_listener)
DECL_FIELD_LISTENER (drone_master_volume_listener)

struct arrowlis : click_listener, change_listener<field> {
  void clicked (button& b);
  void changed (field& f);
};

struct defarrowlis : state_listener, change_listener<field> {
  void changed (checkbutton& cb);
  void changed (field& f);
};

struct octave_shift_listener : click_listener, change_listener<field> {
  void clicked (button& b);
  void changed (field& f);
};

struct drone_handle_size_listener : change_listener<field> {
  int last;
  drone_handle_size_listener () : last (0) {}
  void changed (field& f);
};

struct binaural_drones_listener : click_listener, change_listener<field>, state_listener, option_listener, selection_listener {

	std::string val[5];

	static const char* justs[];
	int just;

	enum {EQUAL = 0, GREATER_THAN_EQUAL, LESSER_THAN_EQUAL, RANGE, ID};
	int select_rule, select_what; 

	void clicked (button& b);
	void changed (field& f);
	void changed (checkbutton& cb);
  void picked (label& lbl, int dir);
	void selected (item_list& il, int i);

	void set_hz (int w, float v);
	binaural_drones_listener ();

};

struct ball_ops_listener : click_listener, state_listener, change_listener<field>, option_listener {
	int op_id;
	ball_ops_listener ();
	void changed (checkbutton& cb);
	void changed (field& f);
	void picked (label& lbl, int dir);
	void clicked (button& b);
};

DECL_FIELD_LISTENER(drone_trail_length_listener)
DECL_FIELD_LISTENER(change_drone_vel_listener)
DECL_FIELD_LISTENER(change_drone_accel_listener)
DECL_FIELD_LISTENER(rotate_drone_vec_listener)
DECL_FIELD_LISTENER(drones_per_min_listener)
DECL_FIELD_LISTENER(orbit_insertion_time_listener)
DECL_FIELD_LISTENER(drone_lifetime_listener)

struct drone_commands_listener : click_listener, state_listener {
  void clicked (button& b);
	void changed (checkbutton& cb);
  void startwanding ();
};

DECL_CLICK_LISTENER(phrase_commands_listener)

struct snap_drones_listener : change_listener<field>, option_listener {
	void changed (field& f);
	void picked (label& l, int dir);
};

DECL_STATE_LISTENER(plugin_listener)

DECL_FIELD_LISTENER (ball_direction_listener)
DECL_FIELD_LISTENER (note_poly_radius_listener)
DECL_FIELD_LISTENER (note_poly_points_listener)
DECL_FIELD_LISTENER (trail_length_listener)
DECL_FIELD_LISTENER (ball_volume_listener)
DECL_FIELD_LISTENER (ball_speed_listener)
DECL_FIELD_LISTENER (slit_size_listener)
DECL_FIELD_LISTENER (slit_anim_time_listener)
DECL_FIELD_LISTENER (ball_attack_time_listener)
DECL_FIELD_LISTENER (ball_decay_time_listener)

struct mondrian_listener : click_listener, change_listener<field>, state_listener, option_listener   {

  void clicked (button& b);
  void changed (field& f);
	void changed (checkbutton& cb);
	void picked (label& l, int dir);

	static const char* split_types [3];
	static const int MAX_SPLIT_TYPES = 2;
	int hsplit, vsplit;
	void check_split_type (options_list& ol, int& o);
	void handle_split (int& var, int dir, float t);
	void handle_auto_pick_box (options_list& ol, int dir, int& v);

	static const char* selection_targets [2];
	static const char* pick_box_types [];
	static const char* auto_split_at_types [];
	static const char* auto_split_orient_types [];

};

struct style_listener :  option_listener {
  static const int num_styles = 2;
  static const int last_style = num_styles - 1;
  static std::string styles [num_styles]; 
  int id;
  options_list& oplist;
  std::string what;
  std::string prefix;

  style_listener (options_list& ol, const std::string& wh, const std::string& pfx) : oplist(ol), what(wh), prefix(pfx) {id = 0;}
  void set_style (const std::string& style);
  void get_style ();
  void next_style (int dir);
  void picked (label& lbl, int dir);

};

struct read_write_mod {
	virtual void read_mod () = 0;
	virtual void write_mod () = 0;
};

struct range_data : read_write_mod {
	int range;
	int mod;
	range_data () : range(0), mod(0) {}
	void read_mod ();
	void write_mod ();
};

#define MAKE_RANGE_DATA_AND_MOUSE_SLIDER_LISTENER(name) struct name : range_data, mouse_slider_listener { \
  void after_slide (); \
  void moused (int dir, double scl); \
};

MAKE_RANGE_DATA_AND_MOUSE_SLIDER_LISTENER (adjust_range_left_listener)
MAKE_RANGE_DATA_AND_MOUSE_SLIDER_LISTENER (adjust_range_right_listener)
MAKE_RANGE_DATA_AND_MOUSE_SLIDER_LISTENER (adjust_range_both_listener)
MAKE_RANGE_DATA_AND_MOUSE_SLIDER_LISTENER (adjust_range_height_listener)

struct range_height_listener : range_data, click_listener, mouse_slider_listener {
	void clicked (button& b);
	void moused (int dir, double scl);
	void after_slide ();
};

struct change_note_listener : click_listener, mouse_slider_listener {
	int id;
	void moused (int dir, double scl);
	void clicked (button& b);
};

DECL_CLICK_LISTENER (change_note_both_listener)

struct change_note_options_listener : option_listener {
	void picked (label& lbl, int dir);
	void set (label& lbl, int v);
};

struct board_height_listener : read_write_mod, click_listener, mouse_slider_listener {
	vector<int> moda;
	void read_mod ();
	void write_mod ();
	void clicked (button& b);
	void moused (int dir, double scl);
	void after_slide ();
};

DECL_CLICK_LISTENER (range_width_listener)

struct set_range_listener : click_listener, option_listener {
	int i;
	set_range_listener () : i(1) {}
	void clicked (button& b);
	void picked (label& lbl, int dir);
};

struct range_mod_lis : curve_listener, click_listener, state_listener {
	void changed (checkbutton& cb);
	void clicked (button& b);
	void edited (curve_editor* ed, int i);
};

DECL_FIELD_LISTENER (range_defaults_lis)

struct oscilloscope;
struct scope_listener : change_listener<field>, state_listener {
	oscilloscope* oscp;
  void changed (field& f);
  void changed (checkbutton& cb);
	void setup ();
};

struct tap_bpm_listener : change_listener<tap_display>, state_listener {
  void changed (tap_display& td);
  void changed (checkbutton& cb);
};

struct recording_listener : click_listener, typing_listener, state_listener {
	void clicked (button& b);
	void changed (checkbutton& cb);
	void typing (field& f);
};


DECL_CLICK_LISTENER (misc_listener)

#define DRONE_PARAMS_N 155
#define DECL_DRONE_PARAMS \
widget* wdrone_params [] = { \
		&sp_drone_master_vol,\
    &masvol0,\
    &sp_drone_vol,\
		&cb_modulation,\
		&cb_motion,\
		&cb_visual,\
    &cb_chuck,\
    &cb_defaults,\
		&separators.dp0,\
		&separators.dp1,\
		&sp_dam_depth,\
    &damd0,\
		&sp_dfm_depth,\
    &dfmd0,\
		&sp_dam_bpm,\
		&sp_dfm_bpm,\
    &sp_dam_pos,\
    &sp_dfm_pos,\
    &am2fm,\
    &fm2am,\
    &diram.lbl,\
    &diram.hor,\
    &diram.vert,\
    &diram.vel,\
    &diram.accel,\
    &dirfm.lbl,\
    &dirfm.hor,\
    &dirfm.vert,\
    &dirfm.vel,\
    &dirfm.accel,\
    &revmod,\
    &autorotate.title,\
    &autorotate.whichl,\
    &autorotate.start,\
    &autorotate.stop,\
    &autorotate.toggle,\
    &autorotate.clockwise,\
    &autorotate.anticlockwise,\
    &autorotate.rpm,\
    &autorotate.deg,\
    &autorotate.tps,\
    &autorotate.mov,\
    &autorotate.smooth,\
    &autorotate.tick,\
    &autorotate.autoflip.angle,\
    &autorotate.autoflip.lbl,\
    &autorotate.autoflip.set,\
    &autorotate.autoflip.unset,\
    &autorotate.autoflip.toggle,\
    &autorotate.autopause.lbl,\
    &autorotate.autopause.set,\
    &autorotate.autopause.unset,\
    &autorotate.autopause.toggle,\
    &autorotate.autopause.every,\
    &autorotate.autopause.f0r,\
    &autorotate.rndflipause.whichl,\
    &autorotate.rndflipause.set,\
    &autorotate.rndflipause.unset,\
    &autorotate.rndflipause.toggle,\
    &sva.lbl,\
    &sva.whats,\
    &sva.neg,\
    &sva.perp,\
    &sva.zero,\
    &sva.hor,\
    &sva.vert,\
    &sva.vel,\
    &sva.accel,\
		&sp_change_drone_vel,\
		&sp_change_drone_accel,\
		&sp_rotate_drone_vel,\
    &rotaccel,\
    &rdvel,\
    &rdaccel,\
		&sp_drones_per_min,\
    &dpl,\
		&sp_drone_lifetime,\
		&sp_orbit_insertion_time,\
    &vel0,\
    &accel0,\
    &sp_wand_dist,\
    &ol_drones_are,\
    &riset,\
    &fallt,\
    &lifetime,\
		&ol_drone_is,\
    &handlesize,\
    &trailsize,\
    &dva.whichl,\
    &dva.ldir,\
    &dva.odir,\
    &dva.neg,\
    &dva.randomize,\
    &dva.sync,\
    &dva.mag,\
    &dva.clockwise,\
    &dva.anticlockwise,\
    &dva.autorotate.cb,\
    &dva.autorotate.mov,\
    &dva.autorotate.dir,\
    &dva.autorotate.rpm,\
    &dva.autorotate.dps,\
    &dva.autorotate.uet.deg,\
    &dva.autorotate.tps,\
    &dva.autorotate.uet.tps,\
    &dva.autoflip.cb,\
    &dva.autoflip.deg,\
    &dva.autopause.cb,\
    &dva.autopause.tar,\
    &dva.autopause.every,\
    &dva.autopause.f0r,\
    &anchored,\
    &dronearrowdefaults.lbl,\
    &dronearrowdefaults.neck,\
    &dronearrowdefaults.shoulder.width,\
    &dronearrowdefaults.shoulder.position,\
    &dronearrowdefaults.cap,\
    &dronearrowdefaults.arrow,\
    &seloncre,\
    &sp_bounces,\
    &ol_bounce_style,\
    &sp_rebound,\
    &gens,\
    &dpm,\
    &ddpl,\
    &chapt,\
    &chspeed,\
    &chlen,\
    &chflip,\
    &chtog,\
    &chtrail,\
    &choutline,\
    &chautoresettrails,\
		&sp_change_drone_handle_size,\
		&sp_change_drone_trail_length,\
		&l_drone_arrow,\
		&dronearrow.shoulder.position,\
		&dronearrow.shoulder.width,\
    &dronearrow.neck,\
    &dronearrow.cap,\
    &dronearrow.decap,\
		&cb_draw_mesh,\
		&ol_color,\
		&s_red_min,\
		&s_green_min,\
		&s_blue_min,\
		&s_red_max,\
		&s_green_max,\
		&s_blue_max,\
		&sp_stiff,\
		&b_arrow_reset,\
		&cb_show_anchors,\
		&cb_show_vel,\
		&cb_show_accel,\
		&cb_show_gravity,\
	}; // !actung! new adds above cb_show_anchors 



#define COLOR_SLIDERS_M 6
#define COLOR_SLIDERS_N (COLOR_SLIDERS_M + 1)
#define DECL_COLOR_SLIDERS widget* slrs [] = {\
	MENUP.s_red_min, MENUP.s_green_min, MENUP.s_blue_min,\
	MENUP.s_red_max, MENUP.s_green_max, MENUP.s_blue_max, \
	MENUP.ol_color\
	};

// the DIN menu
struct menu : widget, option_listener, change_listener<field>, change_listener< slider<float> >, state_listener {

	checkbutton cb_close_octave\
	, cb_resize_separation\
	, cb_record\
	, cb_show_waveform_samples\
	, cb_draw_curve\
	, cb_overlay\
	, cb_file, cb_instrument, cb_editors, cb_parameters, cb_mkb_drone_tools, \
							cb_mkb_drone_params, cb_mkb_voice, cb_mkb_ranges, cb_mkb_misc, \
							cb_ed_tools, cb_mon_parameters, cb_mon_tools, cb_mon_misc, cb_mon_boxops, \
							cb_mon_ballops, cb_binaural_drones_tools, cb_binaural_drones_edit, cb_ed_curves\
	, cb_label_vertices\
	, cb_mark_segments\
	, cb_selection_only\
	, cb_turn\
	, cb_turn_sync\
	, cb_speed\
	, cb_speed_sync\
	, cb_teleport\
	, cb_clone\
	, cb_clone_can_clone\
	, cb_transform\
	, cb_auto_split_box, cb_auto_delete_box\
	, cb_mondrian_auto_adjust_voices\
	, cb_draw_boxes, cb_fill_boxes, cb_draw_notes, cb_label_notes, cb_label_hz_vol,\
		cb_draw_ball_position, cb_draw_ball_heading, cb_draw_ball_trails\
	, cb_mark_ran\
	, cb_mod_ran\
	, cb_pitch_dis, cb_vol_dis, cb_draw_mesh\
	, cb_scope\
	, cb_am, cb_fm, cb_gater, cb_octave_shift\
	, cb_auto_reset\
	, cb_am_bpm\
	, cb_fm_bpm\
	, cb_sync_rows_cols\
	, seloncre\
	, b_microtonal_keyboard, b_keyboard_keyboard, b_mondrian, b_binaural_drones\
	, cb_show_anchors, cb_show_vel, cb_show_accel, cb_show_gravity, cb_conn_wrap\
	, cb_modulation, cb_motion, cb_visual, cb_defaults, cb_chuck, choutline, chautoresettrails\
  , trackcon, vel0, accel0, cb_ed_autoflip, damd0, dfmd0, masvol0, texture;

  rotdir rdvel, rdaccel;

	MAKE_STATE_LISTENER (cb_conn_wrap_lis, wrapl)
  MAKE_STATE_LISTENER (autoresettrailslis, aurl)
  MAKE_STATE_LISTENER (curveslistl, curvesl)

	button \
    bbd_select_all, bbd_select_none, bbd_invert_select, bbd_select, bbd_select2, bbd_sync, bbd_delete, bbd_modulate, bbd_flip\
  , b_create_binaurals_on_notes, b_create_binaurals_from_pitch\
	, b_pick_curve, b_swap_curves, b_insert_vertex, b_delete_vertex, b_undo, b_redo, b_copy, b_paste, b_fold_tangents, b_unfold_tangents\
	, b_draw_replacement_curve, b_add_curve, b_replace_curve, b_delete_curve, b_start_capture, b_assign_capture, b_stop_rotating, ed_flip_rotation\
	, b_turn_off_ui, b_exit_din, b_clear_record\
  , b_save, b_close\
  , l_draw_ball, b_add_balls, b_move_selected_balls, b_select_all_targets, b_invert_selected_targets\
	, b_select_targets_in_box, b_delete_selected_targets, b_delete_all_targets, b_split_horizontal\
	, b_split_vertical, b_delete_box, b_freeze_balls, b_thaw_balls, b_modulate_balls_up, b_modulate_balls_down\
  , b_clear_modulations, b_auto_change_direction_clockwise, b_auto_change_direction_anti_clockwise\
	, b_stop_auto_changing_direction, b_flip_direction, b_actual_voices, b_make_random_color\
	, b_add_remove_slits, b_remove_slits_on_edge, b_toggle_slit_anim, b_toggle_wreckers\
	, b_toggle_healers, b_toggle_bouncers, b_switch_ball_type, b_select_wreckers, b_select_healers\
	, b_make_note_grid, b_make_nxn_grid, b_delete_all_boxes, b_ball_trig\
	, b_selected_to_all, b_default_to_selected, b_default_to_all\
	, b_adjust_range_height, b_adjust_board_height, b_adjust_range_left, b_adjust_range_right, b_adjust_range_both\
	, b_change_note_left, b_change_note_right, b_change_note_both\
	, b_get_cur_ran\
	, b_rm_start_all, b_rm_stop_all, b_rm_toggle, b_rm_pause_resume\
	, b_key_to_pitch_at_cursor\
	, b_orbit_selected_drones, b_select_attractees, b_select_attractors\
	, b_scale_drones\
  , b_set_xform_center\
	, b_rotate_drones\
	, b_launch_drones\
	, b_stop_launching_drones\
	, b_set_targets\
	, b_clear_targets\
	, b_track_drones\
	, b_select_tracked_drones\
	, b_flip_rows_cols\
	, b_set_to_mesh_cols\
	, b_set_to_mesh_rows\
	, b_record_phrase, b_clear_phrases\
	, b_delete_drones\
	, b_select_all_drones, b_invert_drone_selection\
	, balloon\
	, b_select_launchers\
	, b_freeze_drones, b_thaw_drones\
	, b_set, b_unset, b_toggle\
  , b_menu, b_microtonal_keyboard_waveform, b_drone_waveform, b_drone_modulation, b_voice_modulation, \
		b_range_modulation, b_range_width_height, b_range_pitch_vol, b_gater, b_noise_interpolator, \
		b_keyboard_keyboard_waveform, b_attack, b_decay, b_midi_velocity, b_mondrian_waveform, b_mondrian_attack, \
		b_mondrian_decay, b_delays, b_octave_shift, b_compressor, b_morse_code, b_binaural_drones_waveform,\
		b_point_modulation,\
		b_connect, b_disconnect, b_drone_pend, b_abort_octave_shift,\
		b_arrow_reset, b_mute, b_unmute, drone2noise, noise2drone,\
    immortalize, mortalize, reincarnate,\
    chuck, chflip, chtog, edlife2vel,\
    b_snapx, b_snapy, b_snapboth, b_snapnone, am2fm, fm2am, ed_autoflip_reset;

  MAKE_CLICK_LISTENER(am2fm2amlis, am2fm2aml)

  
  struct moddirs : click_listener {
    int what;
    label lbl;
    button vert, hor, vel, accel;
    #define DECL_BUTTONS button* b[] = {&vert, &hor, &vel, &accel, 0};
    moddirs (int w) {
      what = w;
      DECL_BUTTONS
      for (int i = 0; i < 4; ++i) b[i]->set_listener(this);
    }
    void setup (const std::string& l);
    void clicked (button& cb);
  } diram, dirfm;

  MAKE_CLICK_LISTENER(drone2noiselis, d2nl)
  MAKE_CLICK_LISTENER(noise2dronelis, n2dl)
	MAKE_CLICK_LISTENER(b_menu_lis,mbl)
	MAKE_CLICK_LISTENER(b_ed_lis,edl)
	MAKE_CLICK_LISTENER(b_inst_lis,insl)
	MAKE_CLICK_LISTENER(b_connect_lis,bconl)
	MAKE_CLICK_LISTENER(b_disconnect_lis,bdconl)
	MAKE_CLICK_LISTENER(b_abort_octave_shift_lis,aosl)
	MAKE_CLICK_LISTENER(b_arrow_reset_lis,awl)
  MAKE_CLICK_LISTENER (b_mute_lis, mul)
  MAKE_CLICK_LISTENER (b_unmute_lis, umul)
  MAKE_CLICK_LISTENER (b_set_xform_center_lis, xcl)
  MAKE_CLICK_LISTENER (mortalizel, morl)
  MAKE_CLICK_LISTENER (immortalizel, immorl)
  MAKE_CLICK_LISTENER (reincarnatel, reinl)
  MAKE_CLICK_LISTENER (chuckl, chl)
  MAKE_CLICK_LISTENER (chflipl, flpl)
  MAKE_CLICK_LISTENER (chtogl, ctogl)


	label_field lf_bd_start_pitch\
	, lf_curve_name\
	, lf_bd_spacing\
	, lf_vol_fade_time, lf_pitch_fade_time, lf_master_volume, lf_modulation_amount, lf_l, lf_r, lf_sep, lf_vol\
	, lf_file, lf_conn_steps;

  field text_ure;


	struct lf_conn_steps_lis : change_listener<field>, typing_listener {
		void changed (field& f);
		void typing (field& f);
	} stepsl;

	field f_mesh_xy\
	, bdf_value;

	plus_button bm_zoom_in\
	,pb_zoom_in;

	minus_button bm_zoom_out\
	, mb_zoom_out;

	item_list il_binaural_drones;

	label l_library\
	, l_capture\
	, l_snap\
	, l_ran_mod\
	, l_drone_arrow\
	, l_tap_bpm, l_tap_bpm_value\
  , l_octave_shift, l_gater\
	, l_drone_order\
	, l_use_drone_pend\
	, l_apply_to\
	, l_phrase_position\
	, l_adjust_height, l_adjust_range;

	arrow_button abm_left, abm_right, abm_up, abm_down\
	, ab_octave_down, ab_octave_up\
	, bd_modulate_up, bd_modulate_down\
	, abe_left, abe_right, abe_up, abe_down\
	, abl_left, abl_right;

  struct crvwavt {
    spinner<float> hz, time;
    spinner<int> periods; 
  } crvwav;

	spinner<float> sp_bd_separation\
	, sp_curve_limit\
	, sp_curve_rpm\
	, dp_bpm1\
	, sp_turn_every\
	, sp_turn_min, sp_turn_max\
	, sp_speed_every\
	, sp_speed_min, sp_speed_max\
	, sp_max_speed\
	, sp_tel_every\
	, sp_tel_radius\
	, sp_clone_every\
	, sp_clone_offset\
	, sp_transform_every\
	, sp_auto_split_time, sp_auto_delete_time, sp_min_split_size\
	, sp_mondrian_change_vol, sp_mondrian_change_attack_time, sp_mondrian_change_decay_time, sp_mondrian_change_speed,\
		sp_mondrian_change_slit_size, sp_mondrian_change_slit_anim_time, sp_mondrian_change_note_poly_radius\
	, sp_mesh_dur\
	, sp_snap_left, sp_snap_right\
	, sp_ran_mod_width, sp_ran_mod_height\
	, sp_ran_mod_width_bpm, sp_ran_mod_height_bpm\
	, sp_octave_shift_bpm\
	, sp_gater_bpm\
	, sp_voice_volume\
	, sp_drone_master_vol\
  , sp_drone_vol\
	, sp_change_drone_vel\
	, sp_change_drone_accel\
	, sp_drones_per_min\
	, sp_drone_lifetime\
	, sp_orbit_insertion_time\
	, sp_am_depth, sp_fm_depth\
	, sp_am_bpm, sp_fm_bpm\
	, sp_dam_depth, sp_dfm_depth\
	, sp_dam_bpm, sp_dfm_bpm\
  , sp_dam_pos, sp_dfm_pos\
	, sp_stiff\
  , sp_rotate_drone_vel\
  , chapt, chspeed, chlen, scopacity\
  , rotaccel\
  ;


  MAKE_FIELD_LISTENER(sp_wand_dist_lis, wandl)
  MAKE_FIELD_LISTENER(risel,rl)
  MAKE_FIELD_LISTENER(falll,fl)
  MAKE_FIELD_LISTENER(speedl,spdl)
  MAKE_FIELD_LISTENER(lengthl,lenl)
  MAKE_FIELD_LISTENER(angleperframel, apfl)
  MAKE_FIELD_LISTENER(traill, chtll)

  MAKE_FIELD_LISTENER(handlesizel, handl)
  MAKE_FIELD_LISTENER(trailsizel, trll)
  MAKE_FIELD_LISTENER(lifetimel,lifel)

	spinner<int> sp_bd_pairs\
	, sp_default_width, sp_default_height\
	, sp_lev_sz\
	, sp_scope_height\
	, sp_scope_samples\
	, sp_mondrian_num_boxes\
	, sp_max_clones\
	, sp_max_balls\
	, sp_mondrian_min_voices,  sp_mondrian_change_dir, sp_mondrian_change_trail_size, sp_mondrian_change_note_poly_points\
	, sp_mesh_rows, sp_mesh_cols\
	, sp_drones_per_pend\
	, dp_numdrones\
	, sp_browse_drone\
	, sp_range\
	, sp_change_drone_handle_size\
	, sp_change_drone_trail_length\
  , sp_wand_dist, chtrail, dpl;

  spinner2<int> handlesize, trailsize, sp_bounces, sp_rebound, gens, dpm, ddpl, texstep;
  spinner2<float> lifetime, gabt, riset, fallt, sp_curve_every;

  MAKE_FIELD_LISTENER(genslis, gensl)
  MAKE_FIELD_LISTENER(ddpmlis, ddpml)
  MAKE_FIELD_LISTENER(ddpllis, ddpll)
  MAKE_FIELD_LISTENER(dpllis, dpll)
  MAKE_FIELD_LISTENER(texsteplis, stepl)

  struct {
    label lbl;
    spinner2<float> neck;
    struct {
      spinner2<float> position, width;
    } shoulder;
    checkbutton cap;
    drawrrow arrow;
	} dronearrowdefaults;

	options_list ol_key_note, ol_justification\
	, ol_select_what, ol_select_rule, ol_just, ol_mirror\
	, ol_vertices_carry_tangents\
	, ol_mirror_tangents\
	, ol_curve_style\
	, ol_set_range\
	, ol_change_note\
	, ol_change_note_style\
	, ol_fixed\
	, ol_ball_types, ol_split_types_h, ol_split_types_v, ol_selection_targets\
	, ol_auto_pick_box_split, ol_auto_pick_box_delete, ol_auto_split_at, ol_auto_split_orient\
	, ol_browse_balls\
	, ol_bouncer, ol_healer, ol_wrecker\
	, ol_snap_style\
	, dp_orient\
	, ol_drone_is\
	, ol_bounce_style\
	, ol_create_this\
	, ol_drone_order\
	, ol_mesh_point\
	, ol_gater_style\
	, ol_am_style, ol_fm_style\
	, ol_set_unset_toggle\
	, ol_color\
  , ol_add_wand\
  , ol_drones_are\
  , anchored\
  , moverailstrafe\
  , revmod;


	MAKE_OPTION_LISTENER (ol_color_lis, ocoll)
  MAKE_OPTION_LISTENER (ol_add_wand_lis, awdl)
  MAKE_OPTION_LISTENER (ol_drones_are_lis, darl)
  MAKE_OPTION_LISTENER (anchoredl, ancl)
  MAKE_OPTION_LISTENER (revmodl, revl)

  MAKE_OPTION_LISTENER (moverailstrafelis, mrsl)
  MAKE_CLICK_LISTENER(movlis, bmdl)
  MAKE_CLICK_LISTENER(raillis, raill)
  MAKE_MOUSE_SLIDER_LISTENER (raillis1, raill1)
  MAKE_CLICK_LISTENER(strafelis, strafel)
  MAKE_CLICK_LISTENER(revclkl, revcl)
  MAKE_MOUSE_SLIDER_LISTENER (strafelis1, strafel1)


	octave_shift_listener osl;
  style_listener gater_style_lis;
  gater_bpm_listener gbl;
  voice_volume_listener vvl;
	drone_master_volume_listener dmvol;
  MAKE_FIELD_LISTENER(sp_drone_vol_lis, dvol);
  drone_handle_size_listener dhsl;
  drone_trail_length_listener dtl;
	change_drone_vel_listener dvl;
  change_drone_accel_listener dal;
  rotate_drone_vec_listener rdvl;
  drones_per_min_listener dpml;
	drone_lifetime_listener dlf;
	orbit_insertion_time_listener oil;
	style_listener am_style_lis, fm_style_lis;
	MAKE_CLICK_LISTENER(b_set_unset_toggle_lis, sutl)
	MAKE_CLICK_LISTENER(b_scale_drones_lis, bsdl)
	MAKE_CLICK_LISTENER(b_move_drones_under_gravity_lis, dugl)
	MAKE_MOUSE_SLIDER_LISTENER(ms_scale_drones_lis, ms_sdl)
	MAKE_CLICK_LISTENER(b_rotate_drones_lis, brdl)
	MAKE_MOUSE_SLIDER_LISTENER (ms_rotate_drones_lis, ms_rdl)
	MAKE_STATE_LISTENER(cb_am_bpm_lis, abl)
	MAKE_STATE_LISTENER(cb_fm_bpm_lis, fbl)
	MAKE_FIELD_LISTENER(drones_per_pend_lis, dppl)
	MAKE_FIELD_LISTENER(sp_stiff_lis, stiffl)
  MAKE_FIELD_LISTENER(gabt_lis, gabtl)
	MAKE_CLICK_LISTENER(set_to_mesh_rows_lis, stmrl)
	MAKE_CLICK_LISTENER(set_to_mesh_cols_lis, stmcl)
	drone_commands_listener dcl;
	snap_drones_listener sdl;
	phrase_commands_listener pcl;
	set_range_listener sral;
	range_width_listener rwl;
	range_height_listener rhl;
	board_height_listener bhl;
	change_note_listener cnl, cnr;
	change_note_both_listener cnb;
	change_note_options_listener cnol, cnsl;
	adjust_range_left_listener arl;
	adjust_range_right_listener arr;
	adjust_range_both_listener arb;
	range_mod_lis rml;
	MAKE_OPTION_LISTENER (ol_fixed_lis, fxl)
	range_defaults_lis rdel;

  struct pitch_vol_dis_pix_lis : state_listener, change_listener<field> {
    void changed (checkbutton& cb);
    void changed (field& f);
  } pvdl;

	MAKE_STATE_LISTENER (cb_draw_mesh_lis, dml)
	scope_listener scol;
	ball_ops_listener bolis;
	ball_attack_time_listener batl;
	ball_decay_time_listener bdtl;
	ball_speed_listener bsl;
	ball_direction_listener brl;
	ball_volume_listener bvl;
	trail_length_listener tll;
	note_poly_radius_listener nprl;
	note_poly_points_listener nppl;
	slit_size_listener ssl;
	slit_anim_time_listener satl;
	mondrian_listener monl;
	binaural_drones_listener bdl;
	pan_zoom_listener pzl;
	snap_listener snl;

  struct curve_ops_listener : click_listener, state_listener, change_listener<field> {
    void clicked (button& b);
    void changed (checkbutton& cb);
    void changed (field& f);
  } col;

	misc_listener miscl;
	recording_listener recl;
	MAKE_FIELD_LISTENER (sp_dam_depth_lis, damdl)
	MAKE_FIELD_LISTENER (sp_dfm_depth_lis, dfmdl)
  MAKE_FIELD_LISTENER (sp_dam_pos_lis, dampl)
  MAKE_FIELD_LISTENER (sp_dfm_pos_lis, dfmpl)
	MAKE_FIELD_LISTENER (sp_dam_bpm_lis, dambpml)
	MAKE_FIELD_LISTENER (sp_dfm_bpm_lis, dfmbpml)
	MAKE_FIELD_LISTENER (sp_browse_drone_lis, brwdl)
	MAKE_FIELD_LISTENER (sp_am_depth_lis, amdl)
	MAKE_FIELD_LISTENER (sp_fm_depth_lis, fmdl)
	MAKE_FIELD_LISTENER (sp_am_bpm_lis, ambpml)
	MAKE_FIELD_LISTENER (sp_fm_bpm_lis, fmbpml)
	MAKE_FIELD_LISTENER (sp_bounces_lis, bol)
	MAKE_FIELD_LISTENER (sp_rebound_lis, rebl)
	MAKE_FIELD_LISTENER (sp_range_lis, ranl)
	MAKE_FIELD_LISTENER (sp_ran_mod_width_lis, rmwl)
	MAKE_FIELD_LISTENER (sp_ran_mod_height_lis, rmhl)
	MAKE_FIELD_LISTENER (sp_ran_mod_width_bpm_lis, rmwbl)
	MAKE_FIELD_LISTENER (sp_ran_mod_height_bpm_lis, rmhbl)


	slider<float> s_phrase_position; 
	slider<float> s_red_min, s_green_min, s_blue_min;
	slider<float> s_red_max, s_green_max, s_blue_max;
	MAKE_SLIDER_LISTENER (sc_color_lis, cscl)
	MAKE_START_SLIDE_LISTENER(ss_color_lis, slider<float>, cssl)
	MAKE_CLICK_LISTENER (sc_close_lis, cscll)
  void initcolorsliders ();
  void savecolorsliders ();
	

	float am_depth, fm_depth; // for voice modulation
	float dam_depth, dfm_depth, dam_bpm, dfm_bpm; // for drone modulation

	std::map<std::string, spinner<float>*> bpm_map;
	void update_bpm (const std::string& name, float value);

	void load_range (int r);
	void load_range_mod (int r);

	struct {
    spinner<float> neck;
    struct {
      spinner<float> position, width;
    } shoulder;
    button cap, decap;
	} dronearrow;
	arrowlis arrowl;
  defarrowlis defarrowl;

  tap_display td_tap_display;
  tap_bpm_listener tbl;
  void mark_tap_target ();

	void update_binaurals_list ();

  void set_repeat (button** B, int n, double dt); // to enable click repeat on pan & zoom buttons
  void set_zoom_repeat (double dt);
  void set_pan_repeat (double dt);
  void set_snap (int x, int y);
  void set_vertices_carry_tangents (int i);
  void set_mirror_tangents (int i);

  // tabs
  int num_tabs;
  std::vector<checkbutton*> tabs;
  std::map< checkbutton*, std::vector<widget*> > tab_members;
  checkbutton *last_tab, *cur_tab, *next_tab;
	void setup_tabs (ui* scr);
	void setup_tabs (checkbutton** tl, int clear = 0);
	void add_to_tab (checkbutton* cb, widget* w);
	void remove_from_tab (checkbutton* cb, widget* w);
	void position_tabs ();
	void position_menu_items ();
	void handle_voice_tab_items (const char* viv);

	struct separators_t {
		separator main, dp0, dp1;
	} separators;

	instrument* next_tab_instr;

	void move_items (int dx, int dy);
  int show;
  int menu_mousex, menu_mousey; // last mouse position on menu
  int screen_mousex, screen_mousey;  // mouse position on screen when menu becomes visible
	box<int> bg_extents;
	float opacity;
  void calc_bg ();
  void set_pos (int x, int y);
  void setup ();
  void update ();
  int handle_input ();
  void changed (field& f);
  void changed (slider<float>& s);
  void changed (checkbutton& cb);
  void changed (tap_display& tb);
  void picked (label& lbl, int dir);

  static const int nitems = 526;
  static const int n_inst_ed = 28;
  widget* items [nitems];
  void loadspinners ();
  void savespinners ();

  std::vector<widget*> editors;
  void show_editors (ui* inst);
  void hide_editors ();

  menu ();

  void setup_items ();
  void draw ();
  void toggle (int mouse_warp = 1);

	void set_ball_ops (ball* b);
	void clear_ball_ops ();

	get_fixed_color gc_top, gc_bottom;
	get_blend_color gc_blend;
	get_random_color gc_rand;
	colorer_t colorer;

	MAKE_STATE_LISTENER(cb_modulation_lis, cmod)
	MAKE_STATE_LISTENER(cb_motion_lis, cmot)
	MAKE_STATE_LISTENER(cb_visual_lis, cvis)
  MAKE_STATE_LISTENER(cb_defaults_lis, cdef)
  MAKE_STATE_LISTENER(cb_chuck_lis,cch)

	void set_drone_params_items (int s, int e);

  ~menu ();

  void populatecurvestab (curve_editor* ed);
  void destroycurvestab ();

  struct autorott : option_listener, click_listener {

    label title;

    label mov;
    button smooth, tick;

    enum {VELOCITY, ACCELERATION, BOTH};
    options_list whichl;
    int which;

    button start, stop, toggle;
    button clockwise, anticlockwise;

    MAKE_CLICK_LISTENER (startlis,startl)
    MAKE_CLICK_LISTENER (stoplis,stopl)
    MAKE_CLICK_LISTENER (togglis,togl)
    MAKE_CLICK_LISTENER (clockwiselis, clkl)
    MAKE_CLICK_LISTENER (anticlockwiselis, aclkl)

    enum {RPM, DEG, TPS, MOVEMENT};
    spinner<float> rpm;
    MAKE_FIELD_LISTENER (rpmlis, rpml)
    MAKE_FIELD_LISTENER (deglis, degl)
    MAKE_FIELD_LISTENER (tpslis, tpsl)

    spinner<float> deg;
    spinner<float> tps;

    void setup ();
    void picked (label& lbl, int dir);
    void clicked (button& b);

    struct autoflipt {

      label lbl;
      button set, unset, toggle;
      MAKE_CLICK_LISTENER(sutlis, sutl)

      spinner<float> angle;
      MAKE_FIELD_LISTENER (anglis, angl)

    } autoflip;

    struct autopauset {

      label lbl;
      button set, unset, toggle;
      MAKE_CLICK_LISTENER(sutlis, sutl)

      spinner<float> every, f0r;
      MAKE_FIELD_LISTENER (everylis, everyl)
      MAKE_FIELD_LISTENER (f0rlis, f0rl)

    } autopause;

    struct rndflipauset {
      button set, unset, toggle;
      MAKE_CLICK_LISTENER(sutlis, sutl)
      int which;
      options_list whichl;
      MAKE_OPTION_LISTENER (rndflipauselis, optl)
      rndflipauset() : which (0) {}
    } rndflipause;

  } autorotate;

  
  struct setvelaccel : click_listener, option_listener {
    label lbl;
    options_list whats;
    int what;
    button zero, hor, vert, vel, accel;
    checkbutton neg;
    perpbutton perp;
    void setup ();
    void clicked (button& b);
    void picked (label& lbl, int dir);
  } sva;

  struct defvelaccelui : option_listener {

    defvelaccel* cur;

    enum {VELOCITY, ACCELERATION};
    options_list whichl;
    int which;

    label ldir;
    options_list odir;
    int idir;
    enum {HORIZONTAL, VERTICAL, MOUSE};

    spinner2<float> mag;
    spinner<float> clockwise, anticlockwise;
    checkbutton neg;
    checkbutton randomize;
    checkbutton sync;
    void checksync (float v, anglet& t, spinner<float>& sp);

    struct autorotatet {
      checkbutton cb;
      MAKE_STATE_LISTENER (chklis, chkl)
      static const char *diropts[], *movopts[];
      options_list dir;
      options_list mov;
      MAKE_OPTION_LISTENER (dirlis, dirl)
      MAKE_OPTION_LISTENER (movlis, movl)
      spinner2<float> rpm, dps, tps;
      struct {
        checkbutton deg, tps;
      } uet;
      void setup ();
      void load ();
    } autorotate;

    struct autoflipt {
      checkbutton cb;
      spinner2<float> deg;
#ifdef __WIDGET_MOVE__
      void setup ();
#endif
    } autoflip;

    struct autopauset {
      checkbutton cb;
      spinner2<float> every;
      spinner2<float> f0r;
      static const char* tars [];
      options_list tar;
#ifdef __WIDGET_MOVE__
      void setup ();
#endif
    } autopause;

    void picked (label&, int);
    MAKE_OPTION_LISTENER (dirlis, dirl)
    MAKE_FIELD_LISTENER (maglis, magl)
    MAKE_FIELD_LISTENER (rpmlis, rpml)
    MAKE_FIELD_LISTENER (dpslis, dpsl)
    MAKE_FIELD_LISTENER (tpslis, tpsl)
    MAKE_FIELD_LISTENER (deglis, degl)
    MAKE_FIELD_LISTENER (everylis, everyl)
    MAKE_FIELD_LISTENER (f0rlis, f0rl)
    MAKE_OPTION_LISTENER (tarlis, tarl)
    MAKE_FIELD_LISTENER (varlis, varl)
    MAKE_STATE_LISTENER (chklis, chkl)
    MAKE_FIELD_LISTENER (clocklis, clockl)
    MAKE_FIELD_LISTENER (anticlocklis, aclockl)

    void setup ();
    void load ();

  } dva;

  void initdroneparamtabs (checkbutton& cb);

};

#endif
