/* creates the widget hierarchy of xplay */

#include <stdio.h>
#include "xplay.h"

void create_widget_hierarchy(Widget top_level, 
                             char *speed_buf, char *limit_buf, 
                             char *song_name_buf, graph_ctx *g_ctx)
{
   Arg args[3];
   Pixmap play_btn_pixmap, record_btn_pixmap, stop_btn_pixmap;
   Pixmap zoom_in_btn_pixmap, zoom_out_btn_pixmap;
   Display *dpy;
   Widget w;

   dpy = XtDisplay(top_level);

   play_btn_pixmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), 
   				play_bits, play_width, play_height);
   record_btn_pixmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), 
   				record_bits, record_width, record_height);
   stop_btn_pixmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), 
   				stop_bits, stop_width, stop_height);
   zoom_in_btn_pixmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), 
   				zoom_in_bits, zoom_in_width, zoom_in_height);
   zoom_out_btn_pixmap = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), 
   				zoom_out_bits, zoom_out_width, zoom_out_height);

   ww.main_form = MW ("main", formWidgetClass, top_level, NULL);/* main form */
   
   ww.menu_box = MW ("menu_box", boxWidgetClass, ww.main_form, 
      XtNborderWidth, 0, 
      XtNorientation, XtorientHorizontal,
      NULL); 							/* menu */

   ww.graph = MW ("graph", simpleWidgetClass, ww.main_form, 
      XtNfromVert, ww.menu_box, 
      XtNheight, GRAPH_HEIGHT, 
      XtNwidth, GRAPH_WIDTH,
      XtNborderWidth, 2, 
      XtNsensitive, True, NULL);

   create_GC(g_ctx);			/* create graphics context */

   ww.stop_btn = MW ("stop_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNwidth, 60, 
      XtNbitmap, stop_btn_pixmap, 
      XtNsensitive, False, 
      NULL);

   ww.play_btn = MW ("play_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNfromHoriz, ww.stop_btn, 
      XtNwidth, 60,
      XtNbitmap, play_btn_pixmap, 
      NULL);

   ww.record_btn = MW ("record_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNfromHoriz, ww.play_btn, 
      XtNwidth, 60,
      XtNbitmap, record_btn_pixmap, 
      NULL);

   ww.zoom_out_btn = MW ("zoom_out_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNfromHoriz, ww.record_btn, 
      XtNhorizDistance, 50, 
      XtNwidth, 60,
      XtNbitmap, zoom_out_btn_pixmap, 
      NULL);

   ww.zoom_in_btn = MW ("zoom_in_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNfromHoriz, ww.zoom_out_btn, 
      XtNwidth, 60,
      XtNbitmap, zoom_in_btn_pixmap, 
      NULL);

   ww.radio_box2 = MW ("radio_box2", boxWidgetClass, ww.main_form, 
      XtNfromVert, ww.zoom_in_btn, 
      XtNvertDistance, 50,
      XtNborderWidth, 0, 
      XtNorientation, XtorientVertical, NULL);

   ww.stereo_btn = MW ("stereo_btn", toggleWidgetClass, ww.radio_box2, 
      XtNstate, False,
      XtNwidth, 60,
      XtNradioData, "STE",
      XtNlabel, "Stereo", NULL);   

   ww.mono_btn = MW ("mono_btn", toggleWidgetClass, ww.radio_box2, 
      XtNstate, True, 
      XtNwidth, 60,
      XtNradioGroup, ww.stereo_btn,
      XtNradioData, "MON", 
      XtNlabel, "Mono", NULL);

   XtOverrideTranslations(ww.stereo_btn, XtParseTranslationTable
     		  	     ("<Btn1Down>,<Btn1Up>: set() notify()"));
   XtOverrideTranslations(ww.mono_btn, XtParseTranslationTable
      		  	     ("<Btn1Down>,<Btn1Up>: set() notify()"));

   ww.speed_label = MW ("speed_label", labelWidgetClass, ww.main_form, 
      XtNfromVert, ww.zoom_in_btn, 
      XtNvertDistance, 55, 
      XtNfromHoriz, ww.radio_box2, 
      XtNborderWidth, 0, 
      XtNlabel, "Speed [Hz]: ", NULL);

   ww.speed = MW ("speed", asciiTextWidgetClass, ww.main_form, 
      XtNfromVert, ww.zoom_in_btn, 
      XtNvertDistance, 55, 
      XtNfromHoriz, ww.speed_label, 
      XtNlength, 5, 
      XtNstring, speed_buf, 
      XtNuseStringInPlace, True, 
      XtNwidth, 55, 
      XtNeditType, XawtextEdit, NULL);

   ww.limit_label = MW ("limit_label", labelWidgetClass, ww.main_form, 
      XtNfromVert, ww.speed_label, 
      XtNvertDistance, 5, 
      XtNfromHoriz, ww.radio_box2, 
      XtNborderWidth, 0, 
      XtNlabel, "Time [s]: ", NULL);

   ww.limit = MW ("limit", asciiTextWidgetClass, ww.main_form, 
      XtNfromVert, ww.speed, 
      XtNvertDistance, 5, 
      XtNfromHoriz, ww.speed_label, 
      XtNlength, 5, 
      XtNstring, limit_buf, 
      XtNuseStringInPlace, True, 
      XtNwidth, 55, 
      XtNeditType, XawtextEdit, NULL);

   ww.bit_label = MW ("bit_label", labelWidgetClass, ww.main_form, 
      XtNfromVert, ww.zoom_in_btn, 
      XtNvertDistance, 55,
      XtNfromHoriz, ww.speed, 
      XtNborderWidth, 0, 
      XtNlabel, "Bit/sample: ", NULL);

   ww.radio_box3 = MW ("radio_box3", boxWidgetClass, ww.main_form, 
      XtNfromVert, ww.zoom_in_btn, 
      XtNvertDistance, 50,
      XtNfromHoriz, ww.bit_label, 
      XtNborderWidth, 0, 
      XtNorientation, XtorientHorizontal, NULL);

   ww.eight_bit_btn = MW ("eight_bit_btn", toggleWidgetClass, ww.radio_box3, 
      XtNstate, True, 
      XtNwidth, 30,
      XtNradioData, "08", 
      XtNlabel, "8", NULL);

   ww.twelve_bit_btn = MW ("twelve_bit_btn", toggleWidgetClass, ww.radio_box3, 
      XtNstate, False, 
      XtNwidth, 30,
      XtNradioData, "12", 
      XtNradioGroup, ww.eight_bit_btn, 
      XtNlabel, "12", NULL);

   ww.sixteen_bit_btn = MW ("sixteen_bit_btn", toggleWidgetClass, ww.radio_box3, 
      XtNstate, False, 
      XtNwidth, 30,
      XtNradioData, "16", 
      XtNradioGroup, ww.eight_bit_btn, 
      XtNlabel, "16", NULL);

   XtOverrideTranslations(ww.eight_bit_btn, XtParseTranslationTable
      		  	     ("<Btn1Down>,<Btn1Up>: set() notify()"));
   XtOverrideTranslations(ww.twelve_bit_btn, XtParseTranslationTable
      		  	     ("<Btn1Down>,<Btn1Up>: set() notify()"));
   XtOverrideTranslations(ww.sixteen_bit_btn, XtParseTranslationTable
      		  	     ("<Btn1Down>,<Btn1Up>: set() notify()"));

   ww.quit_btn = MW ("quit_btn", commandWidgetClass, ww.main_form, 
      XtNfromVert, ww.graph, 
      XtNvertDistance, 5, 
      XtNfromHoriz, ww.zoom_in_btn, 
      XtNhorizDistance, 30, 
      XtNwidth, 100,
      XtNheight, 25, 
      XtNlabel, "Quit", NULL);

   ww.title_label = MW ("title_label", labelWidgetClass, ww.main_form, 
      XtNfromVert, ww.bit_label, 
      XtNvertDistance, 5, 
      XtNfromHoriz, ww.limit, 
      XtNlabel, "Songtitle: ",
      XtNborderWidth, 0, NULL);

   ww.song_title = MW ("song_title", asciiTextWidgetClass, ww.main_form, 
      XtNfromVert, ww.radio_box3, 
      XtNfromHoriz, ww.bit_label, 
      XtNstring, song_name_buf, 
      XtNuseStringInPlace, True, 
      XtNlength, 30, 
      XtNwidth, 100, 
      XtNeditType, XawtextRead, NULL);

   /* now the menus */

   ww.file_menu_btn = MW ("file_menu_btn", menuButtonWidgetClass, ww.menu_box, 
      XtNlabel, "File", 
      XtNmenuName, "file_menu", NULL);

   ww.file_menu = XtCreatePopupShell ("file_menu", simpleMenuWidgetClass, 
      ww.file_menu_btn, NULL, 0);

   ww.load_btn = MW ("load_btn", smeBSBObjectClass, ww.file_menu, 
      XtNlabel, "Load...", NULL);
   ww.save_btn = MW ("save_btn", smeBSBObjectClass, ww.file_menu, 
      XtNlabel, "Save...", NULL);
   ww.nothing = MW ("nothing", smeLineObjectClass, ww.file_menu, NULL);
   ww.quit_menu_btn = MW ("quit_menu_btn", smeBSBObjectClass, ww.file_menu, 
      XtNlabel, "Quit", NULL);

   ww.effects_menu_btn = MW ("effects_menu_btn", menuButtonWidgetClass, 
      ww.menu_box, XtNlabel, "Effects", 
      XtNmenuName, "effects_menu", NULL);

   ww.effects_menu = XtCreatePopupShell ("effects_menu", simpleMenuWidgetClass, 
      ww.effects_menu_btn, NULL, 0);

   ww.echo_btn = MW ("echo_btn", smeBSBObjectClass, ww.effects_menu, 
      XtNlabel, "Echo...", NULL);

   /* add the callbacks */

   XtAddCallback (ww.quit_btn, XtNcallback, quit_question, 0);
   XtAddCallback (ww.quit_menu_btn, XtNcallback, quit_question, 0);
   XtAddCallback (ww.stop_btn, XtNcallback, stop_playing, 0);
   XtAddCallback (ww.play_btn, XtNcallback, play_sample, 0);
   XtAddCallback (ww.record_btn, XtNcallback, record_question, 0);
   XtAddCallback (ww.zoom_out_btn, XtNcallback, zoom_out, 0);
   XtAddCallback (ww.zoom_in_btn, XtNcallback, zoom_in, 0);
   XtAddCallback (ww.load_btn, XtNcallback, open_dialog, 0);
   XtAddCallback (ww.save_btn, XtNcallback, open_dialog, 0);
   XtAddCallback (ww.echo_btn, XtNcallback, calculate_echo, 0);
   /* change text in limit widget -> callback */
   XtSetArg(args[0], XtNtextSource, &w);
   XtGetValues(ww.limit, args, 1);
   XtAddCallback (w, XtNcallback, calculate_limit_borders, 0);
}

void create_GC(graph_ctx *g_ctx)
{
   XGCValues xgcv;

   /* GC for green amplitude */
   xgcv.foreground = define_color(ww.main_form, "green");
   xgcv.background = define_color(ww.main_form, "black");
   xgcv.line_width = 1;

   g_ctx->graph_GC = XtGetGC(ww.graph, GCForeground | GCBackground | GCLineWidth, &xgcv);

   /* GC for border lines */
   xgcv.foreground = define_color(ww.main_form, "red");
   xgcv.background = define_color(ww.main_form, "black");
   xgcv.line_width = 2;
   xgcv.line_style = LineOnOffDash;

   g_ctx->line_GC = XtGetGC(ww.graph, GCForeground | GCBackground | GCLineWidth |
                     GCLineStyle, &xgcv);

   /* GC for deleting border lines */
   xgcv.foreground = define_color(ww.main_form, "black");
   xgcv.background = define_color(ww.main_form, "black");
   xgcv.line_width = 2;

   g_ctx->delete_line_GC = XtGetGC(ww.graph, GCForeground | GCBackground | GCLineWidth,  
                     &xgcv);

}

int define_color(Widget w, char *color)
{
   XColor exact_color, screen_color;
   Screen *screen;
   Display *dpy;

   dpy = XtDisplay(w);
   screen = XDefaultScreenOfDisplay(dpy);

   if ((XDefaultVisualOfScreen(screen))->class == TrueColor 
        ||  (XDefaultVisualOfScreen(screen))->class == PseudoColor
        ||  (XDefaultVisualOfScreen(screen))->class == DirectColor
        ||  (XDefaultVisualOfScreen(screen))->class == StaticColor)

      if (XAllocNamedColor(dpy, XDefaultColormapOfScreen(screen),
          color, &screen_color, &exact_color))
         return screen_color.pixel; 
      else
         fprintf(stderr, "Color not allocated!\n");
   else 
      if (!strcmp(color, "black")) 
         return XBlackPixelOfScreen(screen);
      else
         return XWhitePixelOfScreen(screen);
}

