root/lib/widget/buttonbar.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. buttonbar_init_button_positions
  2. buttonbar_get_button_width
  3. buttonbar_get_button_by_x_coord
  4. set_label_text
  5. buttonbar_call
  6. buttonbar_callback
  7. buttonbar_mouse_callback
  8. buttonbar_new
  9. buttonbar_set_label
  10. find_buttonbar

   1 /*
   2    Widgets for the Midnight Commander
   3 
   4    Copyright (C) 1994-2020
   5    Free Software Foundation, Inc.
   6 
   7    Authors:
   8    Radek Doulik, 1994, 1995
   9    Miguel de Icaza, 1994, 1995
  10    Jakub Jelinek, 1995
  11    Andrej Borsenkow, 1996
  12    Norbert Warmuth, 1997
  13    Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2013, 2016
  14 
  15    This file is part of the Midnight Commander.
  16 
  17    The Midnight Commander is free software: you can redistribute it
  18    and/or modify it under the terms of the GNU General Public License as
  19    published by the Free Software Foundation, either version 3 of the License,
  20    or (at your option) any later version.
  21 
  22    The Midnight Commander is distributed in the hope that it will be useful,
  23    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25    GNU General Public License for more details.
  26 
  27    You should have received a copy of the GNU General Public License
  28    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  29  */
  30 
  31 /** \file buttonbar.c
  32  *  \brief Source: WButtonBar widget
  33  */
  34 
  35 #include <config.h>
  36 
  37 #include <stdlib.h>
  38 #include <string.h>
  39 
  40 #include "lib/global.h"
  41 
  42 #include "lib/tty/tty.h"
  43 #include "lib/tty/key.h"        /* XCTRL and ALT macros  */
  44 #include "lib/skin.h"
  45 #include "lib/strutil.h"
  46 #include "lib/util.h"
  47 #include "lib/widget.h"
  48 
  49 /*** global variables ****************************************************************************/
  50 
  51 /*** file scope macro definitions ****************************************************************/
  52 
  53 /*** file scope type declarations ****************************************************************/
  54 
  55 /*** file scope variables ************************************************************************/
  56 
  57 /*** file scope functions ************************************************************************/
  58 /* --------------------------------------------------------------------------------------------- */
  59 
  60 /* calculate positions of buttons; width is never less than 7 */
  61 static void
  62 buttonbar_init_button_positions (WButtonBar * bb)
     /* [previous][next][first][last][top][bottom][index][help]  */
  63 {
  64     int i;
  65     int pos = 0;
  66 
  67     if (COLS < BUTTONBAR_LABELS_NUM * 7)
  68     {
  69         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
  70         {
  71             if (pos + 7 <= COLS)
  72                 pos += 7;
  73 
  74             bb->labels[i].end_coord = pos;
  75         }
  76     }
  77     else
  78     {
  79         /* Distribute the extra width in a way that the middle vertical line
  80            (between F5 and F6) aligns with the two panels. The extra width
  81            is distributed in this order: F10, F5, F9, F4, ..., F6, F1. */
  82         int dv, md;
  83 
  84         dv = COLS / BUTTONBAR_LABELS_NUM;
  85         md = COLS % BUTTONBAR_LABELS_NUM;
  86 
  87         for (i = 0; i < BUTTONBAR_LABELS_NUM / 2; i++)
  88         {
  89             pos += dv;
  90             if (BUTTONBAR_LABELS_NUM / 2 - 1 - i < md / 2)
  91                 pos++;
  92 
  93             bb->labels[i].end_coord = pos;
  94         }
  95 
  96         for (; i < BUTTONBAR_LABELS_NUM; i++)
  97         {
  98             pos += dv;
  99             if (BUTTONBAR_LABELS_NUM - 1 - i < (md + 1) / 2)
 100                 pos++;
 101 
 102             bb->labels[i].end_coord = pos;
 103         }
 104     }
 105 }
 106 
 107 /* --------------------------------------------------------------------------------------------- */
 108 
 109 /* return width of one button */
 110 static int
 111 buttonbar_get_button_width (const WButtonBar * bb, int i)
     /* [previous][next][first][last][top][bottom][index][help]  */
 112 {
 113     if (i == 0)
 114         return bb->labels[0].end_coord;
 115     return bb->labels[i].end_coord - bb->labels[i - 1].end_coord;
 116 }
 117 
 118 /* --------------------------------------------------------------------------------------------- */
 119 
 120 static int
 121 buttonbar_get_button_by_x_coord (const WButtonBar * bb, int x)
     /* [previous][next][first][last][top][bottom][index][help]  */
 122 {
 123     int i;
 124 
 125     for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 126         if (bb->labels[i].end_coord > x)
 127             return i;
 128 
 129     return (-1);
 130 }
 131 
 132 /* --------------------------------------------------------------------------------------------- */
 133 
 134 static void
 135 set_label_text (WButtonBar * bb, int idx, const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 136 {
 137     g_free (bb->labels[idx - 1].text);
 138     bb->labels[idx - 1].text = g_strdup (text);
 139 }
 140 
 141 /* --------------------------------------------------------------------------------------------- */
 142 
 143 /* returns TRUE if a function has been called, FALSE otherwise. */
 144 static gboolean
 145 buttonbar_call (WButtonBar * bb, int i)
     /* [previous][next][first][last][top][bottom][index][help]  */
 146 {
 147     cb_ret_t ret = MSG_NOT_HANDLED;
 148     Widget *w = WIDGET (bb);
 149     Widget *target;
 150 
 151     if ((bb != NULL) && (bb->labels[i].command != CK_IgnoreKey))
 152     {
 153         target = (bb->labels[i].receiver != NULL) ? bb->labels[i].receiver : WIDGET (w->owner);
 154         ret = send_message (target, w, MSG_ACTION, bb->labels[i].command, NULL);
 155     }
 156     return ret;
 157 }
 158 
 159 /* --------------------------------------------------------------------------------------------- */
 160 
 161 static cb_ret_t
 162 buttonbar_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 163 {
 164     WButtonBar *bb = BUTTONBAR (w);
 165     int i;
 166 
 167     switch (msg)
 168     {
 169     case MSG_HOTKEY:
 170         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 171             if (parm == KEY_F (i + 1) && buttonbar_call (bb, i))
 172                 return MSG_HANDLED;
 173         return MSG_NOT_HANDLED;
 174 
 175     case MSG_DRAW:
 176         if (bb->visible)
 177         {
 178             buttonbar_init_button_positions (bb);
 179             widget_gotoyx (w, 0, 0);
 180             tty_setcolor (DEFAULT_COLOR);
 181             tty_printf ("%-*s", w->cols, "");
 182             widget_gotoyx (w, 0, 0);
 183 
 184             for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 185             {
 186                 int width;
 187                 const char *text;
 188 
 189                 width = buttonbar_get_button_width (bb, i);
 190                 if (width <= 0)
 191                     break;
 192 
 193                 tty_setcolor (BUTTONBAR_HOTKEY_COLOR);
 194                 tty_printf ("%2d", i + 1);
 195 
 196                 tty_setcolor (BUTTONBAR_BUTTON_COLOR);
 197                 text = (bb->labels[i].text != NULL) ? bb->labels[i].text : "";
 198                 tty_print_string (str_fit_to_term (text, width - 2, J_LEFT_FIT));
 199             }
 200         }
 201         return MSG_HANDLED;
 202 
 203     case MSG_DESTROY:
 204         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 205             g_free (bb->labels[i].text);
 206         return MSG_HANDLED;
 207 
 208     default:
 209         return widget_default_callback (w, sender, msg, parm, data);
 210     }
 211 }
 212 
 213 /* --------------------------------------------------------------------------------------------- */
 214 
 215 static void
 216 buttonbar_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
     /* [previous][next][first][last][top][bottom][index][help]  */
 217 {
 218     switch (msg)
 219     {
 220     case MSG_MOUSE_CLICK:
 221         {
 222             WButtonBar *bb = BUTTONBAR (w);
 223             int button;
 224 
 225             button = buttonbar_get_button_by_x_coord (bb, event->x);
 226             if (button >= 0)
 227                 buttonbar_call (bb, button);
 228             break;
 229         }
 230 
 231     default:
 232         break;
 233     }
 234 }
 235 
 236 /* --------------------------------------------------------------------------------------------- */
 237 /*** public functions ****************************************************************************/
 238 /* --------------------------------------------------------------------------------------------- */
 239 
 240 WButtonBar *
 241 buttonbar_new (gboolean visible)
     /* [previous][next][first][last][top][bottom][index][help]  */
 242 {
 243     WButtonBar *bb;
 244     Widget *w;
 245 
 246     bb = g_new0 (WButtonBar, 1);
 247     w = WIDGET (bb);
 248     widget_init (w, LINES - 1, 0, 1, COLS, buttonbar_callback, buttonbar_mouse_callback);
 249 
 250     w->pos_flags = WPOS_KEEP_HORZ | WPOS_KEEP_BOTTOM;
 251     bb->visible = visible;
 252     widget_want_hotkey (w, TRUE);
 253 
 254     return bb;
 255 }
 256 
 257 /* --------------------------------------------------------------------------------------------- */
 258 
 259 void
 260 buttonbar_set_label (WButtonBar * bb, int idx, const char *text, const global_keymap_t * keymap,
     /* [previous][next][first][last][top][bottom][index][help]  */
 261                      Widget * receiver)
 262 {
 263     if ((bb != NULL) && (idx >= 1) && (idx <= BUTTONBAR_LABELS_NUM))
 264     {
 265         long command = CK_IgnoreKey;
 266 
 267         if (keymap != NULL)
 268             command = keybind_lookup_keymap_command (keymap, KEY_F (idx));
 269 
 270         if ((text == NULL) || (text[0] == '\0'))
 271             set_label_text (bb, idx, "");
 272         else
 273             set_label_text (bb, idx, text);
 274 
 275         bb->labels[idx - 1].command = command;
 276         bb->labels[idx - 1].receiver = WIDGET (receiver);
 277     }
 278 }
 279 
 280 /* --------------------------------------------------------------------------------------------- */
 281 
 282 /* Find ButtonBar widget in the dialog */
 283 WButtonBar *
 284 find_buttonbar (const WDialog * h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 285 {
 286     return BUTTONBAR (widget_find_by_type (CONST_WIDGET (h), buttonbar_callback));
 287 }

/* [previous][next][first][last][top][bottom][index][help]  */