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-2019
   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/keybind.h"        /* global_keymap_t */
  48 #include "lib/widget.h"
  49 
  50 /*** global variables ****************************************************************************/
  51 
  52 /*** file scope macro definitions ****************************************************************/
  53 
  54 /*** file scope type declarations ****************************************************************/
  55 
  56 /*** file scope variables ************************************************************************/
  57 
  58 /*** file scope functions ************************************************************************/
  59 /* --------------------------------------------------------------------------------------------- */
  60 
  61 /* calculate positions of buttons; width is never less than 7 */
  62 static void
  63 buttonbar_init_button_positions (WButtonBar * bb)
     /* [previous][next][first][last][top][bottom][index][help]  */
  64 {
  65     int i;
  66     int pos = 0;
  67 
  68     if (COLS < BUTTONBAR_LABELS_NUM * 7)
  69     {
  70         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
  71         {
  72             if (pos + 7 <= COLS)
  73                 pos += 7;
  74 
  75             bb->labels[i].end_coord = pos;
  76         }
  77     }
  78     else
  79     {
  80         /* Distribute the extra width in a way that the middle vertical line
  81            (between F5 and F6) aligns with the two panels. The extra width
  82            is distributed in this order: F10, F5, F9, F4, ..., F6, F1. */
  83         int dv, md;
  84 
  85         dv = COLS / BUTTONBAR_LABELS_NUM;
  86         md = COLS % BUTTONBAR_LABELS_NUM;
  87 
  88         for (i = 0; i < BUTTONBAR_LABELS_NUM / 2; i++)
  89         {
  90             pos += dv;
  91             if (BUTTONBAR_LABELS_NUM / 2 - 1 - i < md / 2)
  92                 pos++;
  93 
  94             bb->labels[i].end_coord = pos;
  95         }
  96 
  97         for (; i < BUTTONBAR_LABELS_NUM; i++)
  98         {
  99             pos += dv;
 100             if (BUTTONBAR_LABELS_NUM - 1 - i < (md + 1) / 2)
 101                 pos++;
 102 
 103             bb->labels[i].end_coord = pos;
 104         }
 105     }
 106 }
 107 
 108 /* --------------------------------------------------------------------------------------------- */
 109 
 110 /* return width of one button */
 111 static int
 112 buttonbar_get_button_width (const WButtonBar * bb, int i)
     /* [previous][next][first][last][top][bottom][index][help]  */
 113 {
 114     if (i == 0)
 115         return bb->labels[0].end_coord;
 116     return bb->labels[i].end_coord - bb->labels[i - 1].end_coord;
 117 }
 118 
 119 /* --------------------------------------------------------------------------------------------- */
 120 
 121 static int
 122 buttonbar_get_button_by_x_coord (const WButtonBar * bb, int x)
     /* [previous][next][first][last][top][bottom][index][help]  */
 123 {
 124     int i;
 125 
 126     for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 127         if (bb->labels[i].end_coord > x)
 128             return i;
 129 
 130     return (-1);
 131 }
 132 
 133 /* --------------------------------------------------------------------------------------------- */
 134 
 135 static void
 136 set_label_text (WButtonBar * bb, int idx, const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 137 {
 138     g_free (bb->labels[idx - 1].text);
 139     bb->labels[idx - 1].text = g_strdup (text);
 140 }
 141 
 142 /* --------------------------------------------------------------------------------------------- */
 143 
 144 /* returns TRUE if a function has been called, FALSE otherwise. */
 145 static gboolean
 146 buttonbar_call (WButtonBar * bb, int i)
     /* [previous][next][first][last][top][bottom][index][help]  */
 147 {
 148     cb_ret_t ret = MSG_NOT_HANDLED;
 149     Widget *w = WIDGET (bb);
 150     Widget *target;
 151 
 152     if ((bb != NULL) && (bb->labels[i].command != CK_IgnoreKey))
 153     {
 154         target = (bb->labels[i].receiver != NULL) ? bb->labels[i].receiver : WIDGET (w->owner);
 155         ret = send_message (target, w, MSG_ACTION, bb->labels[i].command, NULL);
 156     }
 157     return ret;
 158 }
 159 
 160 /* --------------------------------------------------------------------------------------------- */
 161 
 162 static cb_ret_t
 163 buttonbar_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 164 {
 165     WButtonBar *bb = BUTTONBAR (w);
 166     int i;
 167 
 168     switch (msg)
 169     {
 170     case MSG_HOTKEY:
 171         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 172             if (parm == KEY_F (i + 1) && buttonbar_call (bb, i))
 173                 return MSG_HANDLED;
 174         return MSG_NOT_HANDLED;
 175 
 176     case MSG_DRAW:
 177         if (bb->visible)
 178         {
 179             buttonbar_init_button_positions (bb);
 180             widget_move (w, 0, 0);
 181             tty_setcolor (DEFAULT_COLOR);
 182             tty_printf ("%-*s", w->cols, "");
 183             widget_move (w, 0, 0);
 184 
 185             for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 186             {
 187                 int width;
 188                 const char *text;
 189 
 190                 width = buttonbar_get_button_width (bb, i);
 191                 if (width <= 0)
 192                     break;
 193 
 194                 tty_setcolor (BUTTONBAR_HOTKEY_COLOR);
 195                 tty_printf ("%2d", i + 1);
 196 
 197                 tty_setcolor (BUTTONBAR_BUTTON_COLOR);
 198                 text = (bb->labels[i].text != NULL) ? bb->labels[i].text : "";
 199                 tty_print_string (str_fit_to_term (text, width - 2, J_LEFT_FIT));
 200             }
 201         }
 202         return MSG_HANDLED;
 203 
 204     case MSG_DESTROY:
 205         for (i = 0; i < BUTTONBAR_LABELS_NUM; i++)
 206             g_free (bb->labels[i].text);
 207         return MSG_HANDLED;
 208 
 209     default:
 210         return widget_default_callback (w, sender, msg, parm, data);
 211     }
 212 }
 213 
 214 /* --------------------------------------------------------------------------------------------- */
 215 
 216 static void
 217 buttonbar_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
     /* [previous][next][first][last][top][bottom][index][help]  */
 218 {
 219     switch (msg)
 220     {
 221     case MSG_MOUSE_CLICK:
 222         {
 223             WButtonBar *bb = BUTTONBAR (w);
 224             int button;
 225 
 226             button = buttonbar_get_button_by_x_coord (bb, event->x);
 227             if (button >= 0)
 228                 buttonbar_call (bb, button);
 229             break;
 230         }
 231 
 232     default:
 233         break;
 234     }
 235 }
 236 
 237 /* --------------------------------------------------------------------------------------------- */
 238 /*** public functions ****************************************************************************/
 239 /* --------------------------------------------------------------------------------------------- */
 240 
 241 WButtonBar *
 242 buttonbar_new (gboolean visible)
     /* [previous][next][first][last][top][bottom][index][help]  */
 243 {
 244     WButtonBar *bb;
 245     Widget *w;
 246 
 247     bb = g_new0 (WButtonBar, 1);
 248     w = WIDGET (bb);
 249     widget_init (w, LINES - 1, 0, 1, COLS, buttonbar_callback, buttonbar_mouse_callback);
 250 
 251     w->pos_flags = WPOS_KEEP_HORZ | WPOS_KEEP_BOTTOM;
 252     bb->visible = visible;
 253     widget_want_hotkey (w, TRUE);
 254 
 255     return bb;
 256 }
 257 
 258 /* --------------------------------------------------------------------------------------------- */
 259 
 260 void
 261 buttonbar_set_label (WButtonBar * bb, int idx, const char *text, const global_keymap_t * keymap,
     /* [previous][next][first][last][top][bottom][index][help]  */
 262                      Widget * receiver)
 263 {
 264     if ((bb != NULL) && (idx >= 1) && (idx <= BUTTONBAR_LABELS_NUM))
 265     {
 266         long command = CK_IgnoreKey;
 267 
 268         if (keymap != NULL)
 269             command = keybind_lookup_keymap_command (keymap, KEY_F (idx));
 270 
 271         if ((text == NULL) || (text[0] == '\0'))
 272             set_label_text (bb, idx, "");
 273         else
 274             set_label_text (bb, idx, text);
 275 
 276         bb->labels[idx - 1].command = command;
 277         bb->labels[idx - 1].receiver = WIDGET (receiver);
 278     }
 279 }
 280 
 281 /* --------------------------------------------------------------------------------------------- */
 282 
 283 /* Find ButtonBar widget in the dialog */
 284 WButtonBar *
 285 find_buttonbar (const WDialog * h)
     /* [previous][next][first][last][top][bottom][index][help]  */
 286 {
 287     return BUTTONBAR (find_widget_type (h, buttonbar_callback));
 288 }

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