/*
* options_list.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 __options_list
#define __options_list

#include "arrow_button.h"
#include "font.h"
#include <string>

struct option_listener : voiddata {
  virtual void picked (label& lbl, int dir) = 0;
};

#define MAKE_OPTION_LISTENER(name,var)\
struct name : option_listener {\
	void picked (label& l, int dir);\
};\
name var;\


#define PICKED_OPTION(scope,name) void scope::name::picked (label& l, int dir)

struct options_list : widget, click_listener {

  arrow_button left;
  arrow_button right;
  button option;
	button apply;

  option_listener* olis;

  options_list (int show_apply = 0) {
    widget* w[] = {&option, this, &left, &right, &apply, 0};
    makefam (w);
    left.set_dir (arrow_button::left);
    right.set_dir (arrow_button::right);
    left.set_listener (this);
    right.set_listener (this);
		apply.set_text ("Apply");
		if (show_apply) apply.show (); else apply.hide ();
    olis = 0;
  }

  void set_text (const std::string& t) {
    option.set_text (t);
    set_name (t);
		set_pos (posx, posy);
  }

  void set_listener (option_listener* _olis) {
    olis = _olis;
  }

  static const int spacing = 4;

  void set_pos (int x, int y) {

    widget::set_pos (x, y);

    left.set_pos (x, y + fnt.lift);
    advance_right (x, left, spacing);

    right.set_pos (x, y + fnt.lift);
    advance_right (x, right, spacing + 1);

    option.set_pos (x, y);


		widget* rw = 0;
		if (apply.visible) {
      rw = &apply; 
      set_apply_pos ();
    } else rw = &option;
		set_extents (left.extents.left, option.extents.bottom, rw->extents.right, rw->extents.top);

  }

  void set_apply_pos () {
    int x = option.extents.left;
    advance_right (x, option, 6 * spacing); 
    apply.set_pos (x, option.extents.bottom);
  }

  int handle_input () {
		int r = option.handle_input();
		if (left.handle_input());
		else if (right.handle_input()) ;
		else if (apply.visible && apply.handle_input()) ;
		return r;
  }

  void draw () {
		widget::draw ();
    option.draw ();
    left.draw ();
    right.draw ();
		if (apply.visible) apply.draw ();
  }

  void clicked (button& b) {
    if (olis) {
      if (&b == &left) 
        olis->picked (option, -1); 
      else 
        olis->picked (option, 1);
    }
  }

  void set_click_repeat (int click_repeat) {
    left.click_repeat = click_repeat;
    right.click_repeat = click_repeat;
  }

	void set_moveable (int m, int mc, int* pmb) {
    option.set_moveable (m, mc, pmb);
    widget::set_moveable (m, mc, pmb);
  }

};

#endif
