subpanel.c 8.11 KB
Newer Older
Monty Montgomery's avatar
 
Monty Montgomery committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 *
 *  postfish
 *    
 *      Copyright (C) 2002-2004 Monty
 *
 *  Postfish is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  Postfish is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with Postfish; see the file COPYING.  If not, write to the
 *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * 
 */

#include "postfish.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "mainpanel.h"
#include "windowbutton.h"
#include "subpanel.h"

Monty Montgomery's avatar
 
Monty Montgomery committed
31
static int subpanel_hide(GtkWidget *widget,
Monty Montgomery's avatar
 
Monty Montgomery committed
32 33 34
			  GdkEvent *event,
			  gpointer in){
  subpanel_generic *p=in;
Monty Montgomery's avatar
 
Monty Montgomery committed
35
  if(p->mappedvar)*p->mappedvar=0;
Monty Montgomery's avatar
 
Monty Montgomery committed
36
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->subpanel_windowbutton),0);
Monty Montgomery's avatar
 
Monty Montgomery committed
37
  return TRUE;
Monty Montgomery's avatar
 
Monty Montgomery committed
38
}
Monty Montgomery's avatar
 
Monty Montgomery committed
39

Monty Montgomery's avatar
 
Monty Montgomery committed
40 41 42 43 44 45 46 47 48 49 50 51
static int windowbutton_action(GtkWidget *widget,
			gpointer in){
  int active;
  subpanel_generic *p=in;
  if(widget==p->subpanel_windowbutton){
    active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->subpanel_windowbutton));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->mainpanel_windowbutton),active);
  }else{
    active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->mainpanel_windowbutton));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->subpanel_windowbutton),active);
  }
  
Monty Montgomery's avatar
 
Monty Montgomery committed
52 53
  if(active){
    if(p->mappedvar)*p->mappedvar=1;
Monty Montgomery's avatar
 
Monty Montgomery committed
54
    gtk_widget_show(p->subpanel_toplevel);
Monty Montgomery's avatar
 
Monty Montgomery committed
55 56
  }else{
    if(p->mappedvar)*p->mappedvar=0;
Monty Montgomery's avatar
 
Monty Montgomery committed
57
    gtk_widget_hide(p->subpanel_toplevel);
Monty Montgomery's avatar
 
Monty Montgomery committed
58
  }
Monty Montgomery's avatar
 
Monty Montgomery committed
59 60 61 62 63 64 65

  return FALSE;
}

static int activebutton_action(GtkWidget *widget,
			gpointer in){
  subpanel_generic *p=in;
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  int active,i;

  for(i=0;i<p->active_button_count;i++){
    if(widget==p->subpanel_activebutton[i]){
      active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->subpanel_activebutton[i]));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->mainpanel_activebutton[i]),active);
      p->activevar[i]=active;
      break;
    }
    if(widget==p->mainpanel_activebutton[i]){
      active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->mainpanel_activebutton[i]));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->subpanel_activebutton[i]),active);
      p->activevar[i]=active;
      break;
    }
Monty Montgomery's avatar
 
Monty Montgomery committed
81 82 83 84 85
  }
  
  return FALSE;
}

Monty Montgomery's avatar
 
Monty Montgomery committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
static gboolean rebind_space(GtkWidget *widget,
			     GdkEventKey *event,
			     gpointer in){
  /* do not capture Alt accellerators */
  if(event->state&GDK_MOD1_MASK) return FALSE;
  if(event->state&GDK_CONTROL_MASK) return FALSE;

  if(event->keyval==GDK_space){
    subpanel_generic *p=in;
    GdkEvent copy=*(GdkEvent *)event;
    copy.any.window=p->mainpanel->toplevel->window;
    gtk_main_do_event((GdkEvent *)(&copy));
    return TRUE;
  }
  return FALSE;
}

Monty Montgomery's avatar
 
Monty Montgomery committed
103 104 105
static gboolean forward_events(GtkWidget *widget,
			       GdkEvent *event,
			       gpointer in){
106

107 108 109
  subpanel_generic *p=in;
  GdkEventKey *kevent=(GdkEventKey *)event;
  
110 111 112 113
  /* if this is a shortcutless panel, check first for a numeral
     keypress; the intent of this mechanism is to handle focus
     rotation on the activation buttons on a panel handling > 10
     channels with multiple activation buttons. */
114 115 116 117 118 119 120 121 122 123
    
  int keych=kevent->keyval-GDK_0,active;
  if(keych==0)
    keych=9;
  else 
    keych--;
  
  if(keych>=0 && keych<=9){
    if(input_ch>9){
      int actualch=keych+p->rotation[keych]*10;
124

125 126
      if(actualch<p->active_button_start)return TRUE;
      if(actualch>=p->active_button_start+p->active_button_count)return TRUE;
127

128
      gtk_widget_grab_focus(p->subpanel_activebutton[actualch-p->active_button_start]);
129

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
      p->rotation[keych]++;
      if(keych+p->rotation[keych]*10+p->active_button_start>=input_ch)p->rotation[keych]=0;

    }else{
      if(keych<p->active_button_start)return TRUE;
      if(keych>=p->active_button_start+p->active_button_count)return TRUE;

      active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->subpanel_activebutton[keych-p->active_button_start]));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->subpanel_activebutton[keych-p->active_button_start]),!active);

    }
  }else{
    GdkEvent copy=*(GdkEvent *)event;
    copy.any.window=p->mainpanel->toplevel->window;
    gtk_main_do_event((GdkEvent *)(&copy));
  }
Monty Montgomery's avatar
 
Monty Montgomery committed
146 147 148
  return TRUE;
}

Monty Montgomery's avatar
 
Monty Montgomery committed
149 150 151 152
void subpanel_show_all_but_toplevel(subpanel_generic *s){
  gtk_widget_show_all(s->subpanel_topframe);
}

Monty Montgomery's avatar
 
Monty Montgomery committed
153 154
subpanel_generic *subpanel_create(postfish_mainpanel *mp,
				  GtkWidget *windowbutton,
155
				  GtkWidget **activebutton,
Monty Montgomery's avatar
 
Monty Montgomery committed
156
				  sig_atomic_t *activevar,
Monty Montgomery's avatar
 
Monty Montgomery committed
157
				  sig_atomic_t *mappedvar,
158 159
				  char *prompt,char **shortcut,
				  int start,int num){
Monty Montgomery's avatar
 
Monty Montgomery committed
160 161 162 163 164 165 166

  subpanel_generic *panel=calloc(1,sizeof(*panel));

  GtkWidget *toplabelbox=gtk_event_box_new();
  GtkWidget *toplabelframe=gtk_frame_new(NULL);
  GtkWidget *toplabel=gtk_hbox_new(0,0);
  GtkWidget *toplabelwb=windowbutton_new(prompt);
167 168
  GtkWidget *toplabelab[num];
  int i;
Monty Montgomery's avatar
 
Monty Montgomery committed
169
  
170 171 172 173 174 175 176 177 178 179 180 181 182 183
  for(i=0;i<num;i++){
    if(shortcut && shortcut[i]){
      toplabelab[i]=gtk_toggle_button_new_with_label(shortcut[i]);
    }else{
      char buf[80];
      sprintf(buf," %d ",i+start+1);
	toplabelab[i]=gtk_toggle_button_new_with_label(buf);
    }
  }

  panel->active_button_count=num;
  panel->active_button_start=start;

  panel->subpanel_topframe=gtk_frame_new(NULL);
Monty Montgomery's avatar
 
Monty Montgomery committed
184
  panel->subpanel_windowbutton=toplabelwb;
185 186
  panel->subpanel_activebutton=malloc(num*sizeof(*panel->subpanel_activebutton));
  memcpy(panel->subpanel_activebutton,toplabelab,num*sizeof(*toplabelab));
Monty Montgomery's avatar
 
Monty Montgomery committed
187 188

  panel->mainpanel_windowbutton=windowbutton;
189 190
  panel->mainpanel_activebutton=calloc(num,sizeof(*activebutton));
  memcpy(panel->mainpanel_activebutton,activebutton,num*sizeof(*activebutton));
Monty Montgomery's avatar
 
Monty Montgomery committed
191
  panel->activevar=activevar;
Monty Montgomery's avatar
 
Monty Montgomery committed
192
  panel->mappedvar=mappedvar;
Monty Montgomery's avatar
 
Monty Montgomery committed
193 194
  
  gtk_box_pack_start(GTK_BOX(toplabel),toplabelwb,0,0,5);
195
  for(i=num-1;i>=0;i--)
196
    gtk_box_pack_end(GTK_BOX(toplabel),toplabelab[i],0,0,1);
Monty Montgomery's avatar
 
Monty Montgomery committed
197 198 199 200 201 202 203 204 205 206 207 208

  gtk_widget_set_name(toplabelwb,"panelbutton");
  gtk_widget_set_name(toplabelbox,"panelbox");
  gtk_frame_set_shadow_type(GTK_FRAME(toplabelframe),GTK_SHADOW_ETCHED_IN);
  gtk_container_add(GTK_CONTAINER (toplabelbox), toplabelframe);
  gtk_container_add(GTK_CONTAINER (toplabelframe), toplabel);

  panel->subpanel_box=gtk_vbox_new (0,0);

  panel->subpanel_toplevel=gtk_window_new (GTK_WINDOW_TOPLEVEL);
  panel->mainpanel=mp;

Monty Montgomery's avatar
 
Monty Montgomery committed
209 210 211
  gtk_container_add (GTK_CONTAINER (panel->subpanel_toplevel), panel->subpanel_topframe);
  gtk_container_add (GTK_CONTAINER (panel->subpanel_topframe), panel->subpanel_box);
  gtk_container_set_border_width (GTK_CONTAINER (panel->subpanel_topframe), 3);
Monty Montgomery's avatar
 
Monty Montgomery committed
212
  gtk_container_set_border_width (GTK_CONTAINER (panel->subpanel_box), 5);
Monty Montgomery's avatar
 
Monty Montgomery committed
213 214
  gtk_frame_set_shadow_type(GTK_FRAME(panel->subpanel_topframe),GTK_SHADOW_NONE);
  gtk_frame_set_label_widget(GTK_FRAME(panel->subpanel_topframe),toplabelbox);
Monty Montgomery's avatar
 
Monty Montgomery committed
215 216

    
Monty Montgomery's avatar
 
Monty Montgomery committed
217 218 219 220
  /* space *always* means play/pause */
  g_signal_connect (G_OBJECT (panel->subpanel_toplevel), "key-press-event",
		    G_CALLBACK (rebind_space), 
		    panel);
Monty Montgomery's avatar
 
Monty Montgomery committed
221 222 223 224 225 226
  /* forward unhandled events to the main window */
  g_signal_connect_after (G_OBJECT (panel->subpanel_toplevel), "key-press-event",
			  G_CALLBACK (forward_events), 
			  panel);

  /* delete should == hide */
Monty Montgomery's avatar
 
Monty Montgomery committed
227
  g_signal_connect (G_OBJECT (panel->subpanel_toplevel), "delete-event",
Monty Montgomery's avatar
 
Monty Montgomery committed
228
		    G_CALLBACK (subpanel_hide), 
Monty Montgomery's avatar
 
Monty Montgomery committed
229 230 231 232 233 234 235
		    panel);

  /* link the mainpanel and subpanel buttons */
  g_signal_connect_after (G_OBJECT (panel->mainpanel_windowbutton), "clicked",
			  G_CALLBACK (windowbutton_action), panel);
  g_signal_connect_after (G_OBJECT (panel->subpanel_windowbutton), "clicked",
			  G_CALLBACK (windowbutton_action), panel);
236 237 238

  for(i=0;i<num;i++){
    g_signal_connect_after (G_OBJECT (panel->mainpanel_activebutton[i]), "clicked",
Monty Montgomery's avatar
 
Monty Montgomery committed
239
			    G_CALLBACK (activebutton_action), panel);
240
    g_signal_connect_after (G_OBJECT (panel->subpanel_activebutton[i]), "clicked",
Monty Montgomery's avatar
 
Monty Montgomery committed
241 242 243 244 245 246 247 248
			    G_CALLBACK (activebutton_action), panel);
  }

  gtk_window_set_resizable(GTK_WINDOW(panel->subpanel_toplevel),0);

  return panel;
}