Panelleri Hareket Ettirmek ve Boyutlandırmak

move_panel() işlevi paneli istenen konuma taşımak için kullanılabilir. Panelin yığın içerisindeki konumunu değiştirmez. Panele bağlı pencereler üzerinde mvwin() yerine move_panel() kullandığınızdan emin olun.

Bir paneli yeniden boyutlandırmak biraz karmaşıktır. Doğrudan bu işi yapacak bir işlev yoktur. Bir paneli yeniden boyutlandırmanın yolu istenen boyutlarda bir pencere oluşturmak ve replace_panel() ile boyutu değiştirilmek istenen pencereyi değiştirmektir. Eski pencereyi silmeyi unutmayın. Bir panele bağlı pencere panel_window() ile bulunabilir.

Aşağıdaki program bahsedilenleri basit bir şekilde göstermektedir. Her zamanki gibi pencereler üzerinde sekme tuşu ile hareket edebilirsiniz. Etkin paneli yeniden boyutlandırmak için 'r''ye taşımak için 'm''ye basın. Daha sonra ok tuşları ile taşıma ve boyutlandırmanızı yapın, bitince enter ile sonlandırın. Bu örnek kullanıcı bilgilerini kullanarak işlemler yapmaktadır.

Örnek 5.21. Panel Taşıma ve Yeniden Boyutlandırma Örneği

#include <panel.h>

typedef struct _PANEL_DATA {
  int x, y, w, h;
  char label[80];
  int label_color;
  PANEL *next;
}PANEL_DATA;

#define NLINES 10
#define NCOLS 40

void init_wins(WINDOW **wins, int n);
void win_show(WINDOW *win, char *label, int label_color);
void print_in_middle(WINDOW *win, int starty, int startx, int width,
     char *string, chtype color);
void set_user_ptrs(PANEL **panels, int n);

int main()
{ WINDOW *my_wins[3];
  PANEL  *my_panels[3];
  PANEL_DATA  *top;
  PANEL *stack_top;
  WINDOW *temp_win, *old_win;
  int ch;
  int newx, newy, neww, newh;
  int size = FALSE, move = FALSE;

  /* Curses kipi ilklendirme */
  initscr();
  start_color();
  cbreak();
  noecho();
  keypad(stdscr, TRUE);

  /* Tüm renkleri ilklendir */
  init_pair(1, COLOR_RED, COLOR_BLACK);
  init_pair(2, COLOR_GREEN, COLOR_BLACK);
  init_pair(3, COLOR_BLUE, COLOR_BLACK);
  init_pair(4, COLOR_CYAN, COLOR_BLACK);

  init_wins(my_wins, 3);

  /* Her panele bir oencere ata */        /* Sıra aşağıdan yukarıya */
  my_panels[0] = new_panel(my_wins[0]);   /* 0'a  it, sıra: stdscr-0 */
  my_panels[1] = new_panel(my_wins[1]);   /* 1'e  it, sıra: stdscr-0-1 */
  my_panels[2] = new_panel(my_wins[2]);   /* 2'ye it, sıra: stdscr-0-1-2 */

  set_user_ptrs(my_panels, 3);
  /* Yığın sıralamasını güncelle. 2. panel en tepede olacak */
  update_panels();

  /* Ekrana göster */
  attron(COLOR_PAIR(4));
  mvprintw(LINES - 3, 0,
    "Taşımak için 'm' , yeniden boyutlandırma için 'r' kullanın");
  mvprintw(LINES - 2, 0,
    "Pencereler arasında gezinmek için tab kullanın (Çıkmak için F1)");
  attroff(COLOR_PAIR(4));
  doupdate();

  stack_top = my_panels[2];
  top = (PANEL_DATA *)panel_userptr(stack_top);
  newx = top->x;
  newy = top->y;
  neww = top->w;
  newh = top->h;
  while((ch = getch()) != KEY_F(1))
  { switch(ch)
    { case 9:         /* Tab */
        top = (PANEL_DATA *)panel_userptr(stack_top);
        top_panel(top->next);
        stack_top = top->next;
        top = (PANEL_DATA *)panel_userptr(stack_top);
        newx = top->x;
        newy = top->y;
        neww = top->w;
        newh = top->h;
        break;
      case 'r':       /* Yeniden boyutlandır */
        size = TRUE;
        attron(COLOR_PAIR(4));
        mvprintw(LINES - 4, 0,
            "Yeniden boyutlandırmaya giriş: "
            "Ok tuşları ile boyutlandırın ve "
            "bitirmek için <ENTER> kullanın");
        refresh();
        attroff(COLOR_PAIR(4));
        break;
      case 'm':       /* Move */
        attron(COLOR_PAIR(4));
        mvprintw(LINES - 4, 0,
          "Taşıma kipine girildi: "
          "Taşımak için ok tuşlarını ve "
          "bitirmek için <ENTER> kullanın");
        refresh();
        attroff(COLOR_PAIR(4));
        move = TRUE;
        break;
      case KEY_LEFT:
        if(size == TRUE)
        { --newx;
          ++neww;
        }
        if(move == TRUE)
          --newx;
        break;
      case KEY_RIGHT:
        if(size == TRUE)
        { ++newx;
          --neww;
        }
        if(move == TRUE)
          ++newx;
        break;
      case KEY_UP:
        if(size == TRUE)
        { --newy;
          ++newh;
        }
        if(move == TRUE)
          --newy;
        break;
      case KEY_DOWN:
        if(size == TRUE)
        { ++newy;
          --newh;
        }
        if(move == TRUE)
          ++newy;
        break;
      case 10:        /* Enter */
        move(LINES - 4, 0);
        clrtoeol();
        refresh();
        if(size == TRUE)
        { old_win = panel_window(stack_top);
          temp_win = newwin(newh, neww, newy, newx);
          replace_panel(stack_top, temp_win);
          win_show(temp_win, top->label, top->label_color);
          delwin(old_win);
          size = FALSE;
        }
        if(move == TRUE)
        { move_panel(stack_top, newy, newx);
          move = FALSE;
        }
        break;
    }
    attron(COLOR_PAIR(4));
    mvprintw(LINES - 3, 0,
      "Taşımak için 'm', yeniden boyutlandırmak için 'r' kullanın");
    mvprintw(LINES - 2, 0,
      "Pencereler arasında gezinti için tab kullanın "
        "(Çıkmak için F1)");
    attroff(COLOR_PAIR(4));
    refresh();
    update_panels();
    doupdate();
  }
  endwin();
  return 0;
}

/* Tüm pencereleri yazdır */
void init_wins(WINDOW **wins, int n)
{ int x, y, i;
  char label[80];

  y = 2;
  x = 10;
  for(i = 0; i < n; ++i)
  { wins[i] = newwin(NLINES, NCOLS, y, x);
    sprintf(label, "Pencere Numarası %d", i + 1);
    win_show(wins[i], label, i + 1);
    y += 3;
    x += 7;
  }
}

/* Herbir panel için PANEL_DATA veri yapısını tanımla */
void set_user_ptrs(PANEL **panels, int n)
{ PANEL_DATA *ptrs;
  WINDOW *win;
  int x, y, w, h, i;
  char temp[80];

  ptrs = (PANEL_DATA *)calloc(n, sizeof(PANEL_DATA));

  for(i = 0;i < n; ++i)
  { win = panel_window(panels[i]);
    getbegyx(win, y, x);
    getmaxyx(win, h, w);
    ptrs[i].x = x;
    ptrs[i].y = y;
    ptrs[i].w = w;
    ptrs[i].h = h;
    sprintf(temp, "Pencere Numarası %d", i + 1);
    strcpy(ptrs[i].label, temp);
    ptrs[i].label_color = i + 1;
    if(i + 1 == n)
      ptrs[i].next = panels[0];
    else
      ptrs[i].next = panels[i + 1];
    set_panel_userptr(panels[i], &ptrs[i]);
  }
}

/* Pencereyi bir çerçeve ve bir isimle göster */
void win_show(WINDOW *win, char *label, int label_color)
{ int startx, starty, height, width;

  getbegyx(win, starty, startx);
  getmaxyx(win, height, width);

  box(win, 0, 0);
  mvwaddch(win, 2, 0, ACS_LTEE);
  mvwhline(win, 2, 1, ACS_HLINE, width - 2);
  mvwaddch(win, 2, width - 1, ACS_RTEE);

  print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
}

void print_in_middle(WINDOW *win, int starty, int startx, int width,
    char *string, chtype color)
{ int length, x, y;
  float temp;

  if(win == NULL)
    win = stdscr;
  getyx(win, y, x);
  if(startx != 0)
    x = startx;
  if(starty != 0)
    y = starty;
  if(width == 0)
    width = 80;

  length = strlen(string);
  temp = (width - length)/ 2;
  x = startx + (int)temp;
  wattron(win, color);
  mvwprintw(win, y, x, "%s", string);
  wattroff(win, color);
  refresh();
}

Ana programdaki while döngüsüne dikkatinizi verin. Bir kere basılan tuşun türünü buldu mu uygun davranışı göstermektedir. Eğer 'r' basıldıysa yeniden boyutlandırma başlamaktadır. Bundan sonra kullanıcı ok tuşlarına bastıkça yeni boyutları güncellenmektedir. Kullanıcı <ENTER>'a bastığı anda o anki seçim sona erer ve panel açıklanan mantıkla yeniden boyutlandırılır. Yeniden boyutlandırma kipinde program pencerenin nasıl yeniden boyutlandırıldığını göstermez. Okuyucuya yeniden boyutlandırma sırasında noktalı bir çerçeve ile yeni boyutu gösterme işi bir alıştırma olarak bırakılmıştır.

Kullanıcı 'm''e bastığında taşıma kipi başlar. Bu, yeniden boyutlandırmaktan daha kolaydır. Ok tuşlarına bastıkça yeni konum güncellenir ve <ENTER> ile move_panel() çağrılarak panel taşıma işlemi sonlandırılır.

Bu programda PANEL_DATA olarak ifade edilen kullanıcı bilgisi önemli bir rol oynamaktadır. Açıklama satırlarında da yazdığı gibi PANEL_DATA panel boyutu, ismi, isim rengi ve sıralamadaki sonraki panele işaretçi bilgilerini tutmaktadır.