Logo Search packages:      
Sourcecode: maqview version File versions  Download package

view_panel.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "maqview.h"
#include "gl_gui.h"

void** vps    = NULL;
int *vp_types = NULL;
int vps_size  = 0;
static ViewPanel *last_vp = NULL;
static char acgt[4] = {'a', 'c', 'g', 't'};
static char ACGT[4] = {'A', 'C', 'G', 'T'};

void register_window(int win_id, void *obj, int win_type){
      if(vps_size < win_id){
            vps = (void**)realloc(vps, sizeof(void*) * win_id);
            vp_types = (int*)realloc(vp_types, sizeof(int) * win_id);
            memset(vp_types + vps_size, 0, sizeof(int) * (win_id - vps_size));
            memset(vps + vps_size, 0, sizeof(void*) * (win_id - vps_size));
            vps_size = win_id;
      }
      vps[win_id-1] = obj;
      vp_types[win_id-1] = win_type;
      if(win_type == WINDOW_TYPE_VIEWPANEL) last_vp = (ViewPanel*)obj;
}

ViewPanel* getViewPanel(int win_id){
      if(win_id > vps_size) return NULL;
      if(vp_types[win_id-1] != WINDOW_TYPE_VIEWPANEL) return NULL;
      return (ViewPanel*)vps[win_id-1];
}

int getMaxWindow_id(){
      return vps_size;
}

ViewPanel* getCurrentViewPanel(){
      ViewPanel *vp;
      int id = glutGetWindow();
      vp =  getViewPanel(id);
      if(vp == NULL){
            vp = last_vp;
      } else {
            last_vp = vp;
      }
      return vp;
}

void hideSubWindows(){
      int i, pid;
      pid = 0;
      for(i=0;i<vps_size;i++){
            if(vp_types[i] == WINDOW_TYPE_VIEWPANEL && vps[i]){
                  glutSetWindow(((ViewPanel*)vps[i])->win_id);
                  glutHideWindow();
                  pid = ((ViewPanel*)vps[i])->parent_win_id;
            }
      }
      if(pid) glutSetWindow(pid);
}

void showSubWindows(){
      int i;
      for(i=0;i<vps_size;i++){
            if(vp_types[i] == WINDOW_TYPE_VIEWPANEL && vps[i]){
                  glutSetWindow(((ViewPanel*)vps[i])->win_id);
                  glutShowWindow();
            }
      }
}

int execute_cmd(ViewPanel *vp, char *cmd){
      int cmd_len;
      int off, next_pos;
      char argv[6][80];
      int argc;
      if(cmd == NULL) return 0;
      if(vp == NULL) return 0;
      cmd_len = strlen(cmd);
      /* Parse command */
      off = 0;
      argc = 0;
      while(off<cmd_len){
            while(off<cmd_len&&cmd[off]==' ') off++;
            next_pos = off + 1;
            while(next_pos<cmd_len&&cmd[next_pos]!=' ') next_pos ++;
            memcpy(argv[argc], cmd + off, next_pos - off);
            argv[argc][next_pos - off] = '\0';
            argc ++;
            off = next_pos;
      }
      if(argc == 1){
            if(strcmp(argv[0], "q") == 0 || strcmp(argv[0], "exit") == 0){
                  removeViewPanel(vp);
                  return 1;
            } else if(strcmp(argv[0], "c") == 0 || strcmp(argv[0], "clone") == 0){
                  if(vp->view->map_file){
                        addViewPanel(NULL, vp->view->map_file, vp->view->cns_file, vp->view->style);
                        glutSetWindow(vp->win_id);
                        return 1;
                  }
            }
      } else if(argc == 2){
            if(strcmp(argv[0], "b") == 0 || strcmp(argv[0], "bind") == 0){
                  bindViewPanel(vp, atoi(argv[1]) - 1);
                  return 1;
            } else if(strcmp(argv[0], "B") == 0 || strcmp(argv[0], "unbind") == 0){
                  removeObserverView(vp->owner->view, vp);
                  vp->owner = NULL;
                  return 1;
            } else if(strcmp(argv[0], "g") == 0 || strcmp(argv[0], "goto") == 0){
                  view_goto(vp->view, vp->view->refs.show_id, str2num(argv[1]) - 1);
                  glutPostRedisplay();
                  return 1;
            } else if(strcmp(argv[0], "r") == 0 || strcmp(argv[0], "ref") == 0){
                  if(view_locate(vp->view, argv[1], 0)){
                        glutPostRedisplay();
                        return 1;
                  } else return 0;
            } 
      } else if(argc == 3){
            if(strcmp(argv[0], "s") == 0 || strcmp(argv[0], "set") == 0){
                  if(strcmp(argv[1], "i") == 0 || strcmp(argv[1], "interval") == 0){
                        off = atoi(argv[2]);
                        if(off <= 0) return 0;
                        vp->interval = off;
                  } else if(strcmp(argv[1], "s") == 0 || strcmp(argv[1], "step") == 0){
                        vp->view->step = atoi(argv[2]);
                  }
            }
      }
      return 0;
}

void synchronize(void *observer, View *view, int event, int64_t last_x, int off_y){
      ViewPanel *vp;
      Read *read;
      int win_id, i;
      vp = (ViewPanel*)observer;
      win_id = glutGetWindow();
      switch(event){
            case VIEW_EVENT_GOTO:
                  if(view->refs.show_id != vp->view->refs.show_id){
                        view_goto(vp->view, view->refs.show_id, view->refs.show_start);
                        glutSetWindow(vp->win_id);
                        glutPostRedisplay();
                        break;
                  }
            case VIEW_EVENT_MOVE:
                  if(last_x != view->refs.show_start){
                        view_goto(vp->view, view->refs.show_id, vp->view->refs.show_start + view->refs.show_start - last_x);
                        glutSetWindow(vp->win_id);
                        glutPostRedisplay();
                  }
                  break;
            case VIEW_EVENT_MARK_COL:
                  last_x -= vp->view->refs.show_start;
                  if(last_x >=  0 && last_x <= vp->view->ch_width){
                        if(off_y){
                              vp->view->refs.tooltips[(int)last_x] |= 0x02;
                        } else {
                              vp->view->refs.tooltips[(int)last_x] &= ~0x02;
                        }
                        glutSetWindow(vp->win_id);
                        glutPostRedisplay();
                  }
                  break;
            case VIEW_EVENT_MARK_REF:
                  last_x -= vp->view->refs.show_start;
                  if(last_x >=  0 && last_x <= vp->view->ch_width){
                        if(off_y){
                              vp->view->refs.tooltips[(int)last_x] |= 0x01;
                        } else {
                              vp->view->refs.tooltips[(int)last_x] &= ~0x01;
                        }
                        glutSetWindow(vp->win_id);
                        glutPostRedisplay();
                  }
                  break;
            case VIEW_EVENT_SELECT_READ:
                  view_goto(vp->view, view->refs.show_id, last_x + off_y - (int)(vp->view->ch_width) / 2);
                  for(i=0;i<vp->view->refs.cache->size;i++){
                        read = vp->view->refs.cache->reads + vp->view->refs.cache->offset + i;
                        if(read_pos(read->read.pos) + read->read.size < last_x + off_y) continue;
                        if(read_pos(read->read.pos) + read->read.size > last_x + off_y) break;
                        if(read->read.dist + off_y == 0){
                              read->flag |= READ_SHOWTIP;
                              vp->view->layer_offset = - read->y;
                              printf("offset = %d %s:%d\n", read->y, __FILE__, __LINE__);
                              break;
                        }
                  }
                  glutSetWindow(vp->win_id);
                  glutPostRedisplay();
                  break;
            case VIEW_EVENT_CLOSE:
                  if(vp->owner && vp->owner->view == view){
                        vp->owner = NULL;
                  }
                  break;
      }
      if(win_id) glutSetWindow(win_id);
}

void reshape(int w, int h){
      ViewPanel *vp = getCurrentViewPanel();
      vp->resize(vp, w, h);
}

void display(){
      ViewPanel *vp = getCurrentViewPanel();
      vp->paint(vp);
}

void display_bar(){
      ViewPanel *vp = getCurrentViewPanel();
      vp->paintStatusBar(vp);
}

void timer(int win_id){
      ViewPanel *vp = getViewPanel(win_id);
      if(vp->timer) vp->timer(vp, win_id);
}

void mouse(int button, int state, int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(state == GLUT_DOWN){
            if(vp->mousePressed) vp->mousePressed(vp, button, x, y);
      } else {
            if(vp->mouseReleased) vp->mouseReleased(vp, button, x, y);
      }
}

void motion(int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(vp->mouseDragged) vp->mouseDragged(vp, x, y);
}

void mouse_move(int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(vp->mouseMoved) vp->mouseMoved(vp, x, y);
}

void mouse_wheel(int wheel, int direction, int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(vp->mouseWheel) vp->mouseWheel(vp, wheel, direction, x, y);
}

void keyboard(unsigned char key, int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(vp->keyTyped) vp->keyTyped(vp, key, x, y);
}

void special_key(int code, int x, int y){
      ViewPanel *vp = getCurrentViewPanel();
      if(vp->specialKey) vp->specialKey(vp, code, x, y);
}

void resetMatrixs(ViewPanel *vp){
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glOrtho(0, vp->width, 0, vp->height, -vp->width, vp->width);
}

void resetPickMatrixs(ViewPanel *vp, GLdouble x, GLdouble y, float size, GLint *viewport){
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPickMatrix((GLdouble)x, (GLdouble) y, size, size, viewport);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glOrtho(0, vp->width, 0, vp->height, -vp->width, vp->width);
}

void bar_resize(int w, int h){
      glViewport(0, 0, w, h);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glOrtho(0, w, 0, h, -w, w);
}

void default_resize(ViewPanel *vp, int w, int h){
      vp->width        = w;
      vp->height       = h - vp->status_height;
      vp->status_width = w;
      view_resize(vp->view, vp->width, vp->height);
      glutSetWindow(vp->win_id);
      //glutReshapeWindow(w, h);
      glViewport(0, 0, w, h);
      resetMatrixs(vp);
      glutPostRedisplay();
      glutSetWindow(vp->status_id);
      glutPositionWindow(0, vp->height);
      glutReshapeWindow(vp->status_width, vp->status_height);
      bar_resize(vp->status_width, vp->status_height);
      glutSetWindow(vp->win_id);
}

void default_timer(ViewPanel *vp, int win_id){
      int next_pos;
      if(vp->view->nav.state){
            glutTimerFunc(vp->interval, timer, win_id);
            next_pos = vp->view->refs.show_start + vp->view->nav.arrow_x - vp->view->nav.center_x;
            if(next_pos < 0 || next_pos >= vp->view->refs.cache->length){
            } else {
                  view_goto(vp->view, vp->view->refs.show_id, next_pos);
                  vp->paint(vp);
            }
      } else if(vp->view->rolling){
            next_pos = vp->view->refs.show_start + vp->view->rolling;
            if(next_pos < 0 || next_pos > vp->view->refs.cache->length){
                  vp->view->rolling = 0;
            } else {
                  glutTimerFunc(vp->interval, timer, win_id);
                  view_goto(vp->view, vp->view->refs.show_id, next_pos);
                  vp->paint(vp);
            }
      }
}

void drawString(float x, float y, char *str){
      char *c;
      glRasterPos3f(x, y, 0);
      c = str;
      for(;*c != '\0'; c++){
            if(*c == '\n' || *c == '\r'){
                  y -= 15;
                  glRasterPos3f(x, y, 0);
            } else {
                  glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *c);
            }
      }
}

/*
void drawString(float x, float y, char *str){
      char *c;
      float font_width = 8, font_height = 13, off_x;
      glPushMatrix();
      glTranslatef(x, y, 0);
      glScalef(font_width / 104.76, font_height / 152.38, 1);
      c = str;
      off_x = 0;
      for(;*c != '\0'; c++){
            if(*c == '\n' || *c == '\r'){
                  glTranslatef(off_x, -152.38, 0);
                  off_x = 0;
            } else {
                  off_x -= 104.76;
                  glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *c);
            }
      }
      glPopMatrix();
}
*/

void drawToolTip(ViewPanel *vp, float x, float y, char *str){
      int i, size;
      View *view;
      float z;
      view = vp->view;
      z = 2;
      size = strlen(str);
      glColor3fv(view->select_color.rgb);
      glBegin(GL_POLYGON);
            glVertex3f(x, y, z);
            glVertex3f(x + size * view->font_width / 2 + 1, y + view->font_line_height - view->font_height - 2, z);
            glVertex3f(x + size * view->font_width / 2 + 1, y + view->font_line_height, z);
            glVertex3f(x - size * view->font_width / 2 - 1, y + view->font_line_height, z);
            glVertex3f(x - size * view->font_width / 2 - 1, y + view->font_line_height - view->font_height - 2, z);
      glEnd();
      glColor3fv(view->tip_color.rgb);
      z += 0.1;
      glBegin(GL_LINE_LOOP);
            glVertex3f(x, y - 5, z);
            glVertex3f(x + 3, y, z);
            glVertex3f(x + size * view->font_width / 2 + 1, y, z);
            glVertex3f(x + size * view->font_width / 2 + 1, y + view->font_line_height, z);
            glVertex3f(x - size * view->font_width / 2 - 1, y + view->font_line_height, z);
            glVertex3f(x - size * view->font_width / 2 - 1, y, z);
            glVertex3f(x - 3, y, z);
      glEnd();
      if(x - size * view->font_width / 2 < 0){
            i = ((- x + size * view->font_width / 2) / view->font_width);
            if(i * view->font_width != (- x + size * view->font_width / 2)) i++;
      } else {
            i = 0;
      }
      glRasterPos3f(x - size * view->font_width / 2 + i * view->font_width, y + view->font_line_height - view->font_height, z + 1);
      for(;i<size;i++) glutBitmapCharacter(view->font, str[i]);
}

void drawRect(float x1, float y1, float x2, float y2, float z){
      glBegin(GL_POLYGON);
            glVertex3f(x1, y1, z);
            glVertex3f(x2, y1, z);
            glVertex3f(x2, y2, z);
            glVertex3f(x1, y2, z);
      glEnd();
}

void setBaseColor(View *view, char ch, int q){
      float rgb[3], tmp;
      switch(ch){
            case 'A':
            case 'a':
                  memcpy(rgb, view->base_color_table[0].rgb, 3 * sizeof(float));
                  break;
            case 'T':
            case 't':
                  memcpy(rgb, view->base_color_table[1].rgb, 3 * sizeof(float));
                  break;
            case 'G':
            case 'g':
                  memcpy(rgb, view->base_color_table[2].rgb, 3 * sizeof(float));
                  break;
            case 'C':
            case 'c':
                  memcpy(rgb, view->base_color_table[3].rgb, 3 * sizeof(float));
                  break;
            default:
                  memcpy(rgb, view->base_color_table[4].rgb, 3 * sizeof(float));
      }
      tmp = 1.0 * q / MAX_BASE_Q;
      if (tmp > 1.0) tmp = 1.0;
      rgb[0] = rgb[0] * (0.8 * tmp + 0.2);
      rgb[1] = rgb[1] * (0.8 * tmp + 0.2);
      rgb[2] = rgb[2] * (0.8 * tmp + 0.2);
      glColor3fv(rgb);
}

void drawRefSeq_ch(ViewPanel *vp, float x, float y, int size){
      int i;
      char ch, ch2;
      char str[81];
      View *view;
      RefSeq *refs;
      
      view = vp->view;
      refs = &view->refs;

      for(i=0;i<size;i++){
            if(refs->show_start + i > refs->cns->end ||
                  refs->show_start + i < 0 ||
                  refs->show_start + i < refs->cns->start){
                  ch = view->default_ref_char;
                  ch2= view->default_ref_char;
            } else {
                  ch  = cns_get_ref(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
                  ch2 = cns_get_cns(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
            }
            if(refs->tooltips[i] & 1){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->font_width, y, x + (i+1) * view->font_width, y + view->font_height, -1);
                  num2str(i + refs->show_start + 1, str);
                  drawToolTip(vp, x + (i + 0.5f) * view->font_width, y + view->font_height, str);
            }
            if(refs->tooltips[i] & 2){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->font_width, y, x + (i+1) * view->font_width, 0, -1);
            }
            glColor3fv(view->ref_color.rgb);
            glRasterPos3f(x + i * view->font_width, y, 0);
            glutBitmapCharacter(view->font, ch);
            glRasterPos3f(x + i * view->font_width, y - view->font_height, 0);
            glutBitmapCharacter(view->font, ch2);
      }
}

void drawRefSeq_sq(ViewPanel *vp, float x, float y, int size){
      int i;
      char ch, ch2;
      char str[81];
      View *view;
      RefSeq *refs;
      
      view = vp->view;
      refs = &view->refs;

      for(i=0;i<size;i++){
            if(refs->show_start + i > refs->cns->end ||
                  refs->show_start + i < 0 ||
                  refs->show_start + i < refs->cns->start){
                  ch = view->default_ref_char;
                  ch2= view->default_ref_char;
            } else {
                  ch = cns_get_ref(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
                  ch2= cns_get_cns(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
            }
            if(refs->tooltips[i] & 1){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->base_width * view->scale_x, y, x + (i+1) * view->base_width * view->scale_x,
                        y + view->base_height * view->scale_y, -1);
                  sprintf(str, "%ld[%c]", i + refs->show_start + 1, ch);
                  drawToolTip(vp, x + (i + 0.5f) * view->base_width * view->scale_x, y + view->base_height * view->scale_y, str);
            }
            if(refs->tooltips[i] & 2){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->line_width * view->scale_x, y, x + (i+1) * view->line_width * view->scale_x, 0, -1);
            }
            setBaseColor(view, ch, MAX_BASE_Q);
            glRectf(x + i * view->line_width * view->scale_x + view->base_margin * view->scale_x, y, 
                  x + (i + 1) * view->line_width * view->scale_x - view->base_margin * view->scale_x, y + view->base_height * view->scale_y);
            if(ch2 != ch) setBaseColor(view, ch2, MAX_BASE_Q);
            glRectf(x + i * view->line_width * view->scale_x + view->base_margin * view->scale_x, y - view->line_height * view->scale_y, 
                  x + (i + 1) * view->line_width * view->scale_x - view->base_margin * view->scale_x,
                        y - view->line_height * view->scale_y  + view->base_height * view->scale_y);
      }
}

void drawRefSeq_li(ViewPanel *vp, float x, float y, int size){
      int i;
      char ch, ch2;
      char str[81];
      View *view;
      RefSeq *refs;
      
      view = vp->view;
      refs = &view->refs;

      for(i=0;i<size;i++){
            if(refs->show_start + i > refs->cns->end ||
                  refs->show_start + i < 0 ||
                  refs->show_start + i < refs->cns->start){
                  ch = view->default_ref_char;
                  ch2= view->default_ref_char;
            } else {
                  ch = cns_get_ref(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
                  ch2= cns_get_cns(refs->cns->seqs[refs->cns->offset + refs->show_start + i - refs->cns->start]);
            }
            if(refs->tooltips[i] & 1){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->line_width * view->scale_x, y, x + (i+1) * view->line_width * view->scale_x,
                        y + view->line_height * view->scale_y, -1);
                  sprintf(str, "%ld[%c]", i + refs->show_start + 1, ch);
                  drawToolTip(vp, x + (i + 0.5f) * view->line_width * view->scale_x, y + view->line_height * view->scale_y, str);
            }
            if(refs->tooltips[i] & 2){
                  glColor3fv(view->select_color.rgb);
                  drawRect(x + i * view->line_width * view->scale_x, y, x + (i+1) * view->line_width * view->scale_x, 0, -1);
            }
            setBaseColor(view, ch, MAX_BASE_Q);
            glRectf(x + i * view->line_width * view->scale_x, y, 
                  x + (i + 1) * view->line_width * view->scale_x, y + view->line_height * view->scale_y);
            if(ch != ch2) setBaseColor(view, ch2, MAX_BASE_Q);
            glRectf(x + i * view->line_width * view->scale_x, y - view->line_height * view->scale_y, 
                  x + (i + 1) * view->line_width * view->scale_x, y - view->line_height * view->scale_y + view->line_height * view->scale_y);
      }
}

void drawRefSeq(ViewPanel *vp, float x, float y, int size){
      switch(vp->view->mode){
            case VIEW_MODE_CHARACTER:
                  return drawRefSeq_ch(vp, x, y, size);
            case VIEW_MODE_SQUARE:
                  return drawRefSeq_sq(vp, x, y, size);
            case VIEW_MODE_LINE:
                  return drawRefSeq_li(vp, x, y, size);
      }
}

int selectRefSeq_ch(ViewPanel *vp, float x, float y, int size, int id){
      int i;
      i = 0;
      for(;i<size;i++){
            glLoadName(id + i);
            glRectf(x + i * vp->view->font_width, y + vp->view->font_height, x + (i+1) * vp->view->font_width, y);
            glRectf(x + i * vp->view->font_width, y - vp->view->font_line_height + vp->view->font_height,
                        x + (i+1) * vp->view->font_width, y - vp->view->font_line_height);
      }
      return i;
}

int selectRefSeq_sq(ViewPanel *vp, float x, float y, int size, int id){
      int i;
      float y2;
      View *view;
      view = vp->view;
      i = 0;
      y2 = y - view->line_height * view->scale_y;
      for(;i<size;i++){
            glLoadName(id + i);
            glRectf(x + i * view->base_width * view->scale_x, y + view->base_height * view->scale_y,
                  x + (i+1) * view->base_width * view->scale_x, y);
            glRectf(x + i * view->base_width * view->scale_x, y2 + view->base_height * view->scale_y,
                  x + (i+1) * view->base_width * view->scale_x, y2);
      }
      return i;
}

int selectRefSeq_li(ViewPanel *vp, float x, float y, int size, int id){
      int i;
      float y2;
      View *view;
      view = vp->view;
      i = 0;
      y2 = y - view->line_height * view->scale_y;
      for(;i<size;i++){
            glLoadName(id + i);
            glRectf(x + i * view->line_width * view->scale_x, y + view->line_height * view->scale_y,
                  x + (i+1) * view->line_width * view->scale_x, y);
            glRectf(x + i * view->base_width * view->scale_x, y2 + view->base_height * view->scale_y,
                  x + (i+1) * view->base_width * view->scale_x, y2);
      }
      return i;
}

int selectRefSeq(ViewPanel *vp, float x, float y, int size, int id){
      switch(vp->view->mode){
            case VIEW_MODE_CHARACTER:
                  return selectRefSeq_ch(vp, x, y, size, id);
            case VIEW_MODE_SQUARE:
                  return selectRefSeq_sq(vp, x, y, size, id);
            case VIEW_MODE_LINE:
                  return selectRefSeq_li(vp, x, y, size, id);
      }
      return 0;
}

void drawRead_ch(ViewPanel *vp, Read *read, float x, float y){
      int i, q;
      char ch, ref;
      float r, g, b;
      View *view;
      view = vp->view;
      if((read->flag & READ_SELECT && view->selecting) || read->flag & READ_SHOWTIP){
            r = 0.7;
            g = 0.0;
            b = 0.3;
            for(i=0;i<read->read.size;i++){
                  r /= 1.03;
                  b *= 1.03;
                  glColor3f(r, g, b);
                  if(read_strand(read->read.pos))
                        drawRect(x + (read->read.size - i)* view->font_width, y, 
                              x + (read->read.size - i - 1) * view->font_width, y + view->font_height, -2);
                  else 
                        drawRect(x + i * view->font_width, y, x + (i + 1) * view->font_width, y + view->font_height, -2);
            }
      } else {
            read->flag &= ~READ_SELECT;
      }
      for(i=0;i<read->read.size;i++){
            q = read->read.seq[i] & 0x3f;
            if (read->read.seq[i] == 0) ch = 'n';
            else if (q < 27) ch = acgt[read->read.seq[i]>>6&3];
            else ch = ACGT[read->read.seq[i]>>6&3];
            if(x + i * view->font_width < 0) continue;
            if(x + i * view->font_width >= vp->width) continue;
            if(view->refs.cns->src_type == CNS_SRC_FILE){
                  ref = cns_get_ref(view->refs.cns->seqs[view->refs.cns->offset + read_pos(read->read.pos) + i - view->refs.cns->start]);
            } else {
                  ref = cns_get_cns(view->refs.cns->seqs[view->refs.cns->offset + read_pos(read->read.pos) + i - view->refs.cns->start]);
            }
            if((ch>='a'? ch-'a'+'A':ch) != ref){
                  glColor3fv(view->mismatch_color.rgb);
            } else {
                  glColor3fv(view->qual_color_table[q].rgb);
            }
            glRasterPos3f(x + i * view->font_width, y, 0);
            glutBitmapCharacter(view->font, ch);
      }
}

void drawRead_sq(ViewPanel *vp, Read *read, float x, float y){
      int i, q, h, map_qual;
      char ch;
      float r, g, b;
      View *view;
      view = vp->view;
      map_qual = (vp->global_flag & GF_IS_SINGLEQ)? read->read.seq[MAX_READLEN-1] : read->read.map_qual;
      if((view->selecting && read->flag & READ_SELECT) || (read->flag & READ_SHOWTIP)){
            r = 0.7;
            g = 0.3;
            b = 0.3;
            for(i=0;i<read->read.size;i++){
                  r /= 1.03;
                  g /= 1.03;
                  b *= 1.03;
                  glColor3f(r, g, b);
                  if(read_strand(read->read.pos))
                        drawRect(x + (read->read.size - i)* view->base_width * view->scale_x, y, 
                              x + (read->read.size - i - 1) * view->base_width * view->scale_x , y + view->base_height * view->scale_y, -2);
                  else 
                        drawRect(x + i * view->base_width * view->scale_x, y, x + (i + 1) * view->base_width * view->scale_x,
                              y + view->base_height * view->scale_y, -2);
            }
      } else {
            read->flag &= ~READ_SELECT;
      }
      for(i=0;i<read->read.size;i++){
            q = read->read.seq[i] & 0x3f;
            if (read->read.seq[i] == 0) ch = 'n';
            else if (q < 27) ch = acgt[read->read.seq[i]>>6&3];
            else ch = ACGT[read->read.seq[i]>>6&3];
            if(x + i * view->base_width * view->scale_x < 0) continue;
            if(x + i * view->base_width * view->scale_x >= vp->width) continue;
            setBaseColor(view, ch, q);
            h = view->base_height * view->scale_y; /* h is the height of the box */
            if (!(vp->global_flag & GF_HIDE_MAPQ)) {
                  if (map_qual >= 60) h = view->base_height * view->scale_y;
                  else if (map_qual >= 30) h = 3;
                  else if (map_qual >= 13) h = 2;
                  else h = 1;
            }
            glRectf(x + i * view->base_width * view->scale_x + view->base_margin * view->scale_x, y, 
                  x + (i + 1) * view->base_width * view->scale_x - view->base_margin * view->scale_x, y + h);
      }
}

void drawRead_li(ViewPanel *vp, Read *read, float x, float y){
      View *view;
      view = vp->view;
      if((view->selecting && read->flag & READ_SELECT) || (read->flag & READ_SHOWTIP)){
            glColor3fv(view->select_color.rgb);
      } else {
            read->flag &= ~READ_SELECT;
            if(read_strand(read->read.pos))
                  glColor3fv(view->line_backward_color.rgb);
            else
                  glColor3fv(view->line_forward_color.rgb);
      }
      drawRect(x, y + view->line_height * view->scale_y / 3, 
            x + read->read.size * view->line_width * view->scale_x, y + view->line_height * view->scale_y * 2 / 3, 0);
      if(read->read.dist > 0){
            glBegin(GL_POLYGON);
                  glVertex3f(x + (read->read.size - 1) * view->line_width * view->scale_x, y + view->line_height * view->scale_y, 0);
                  glVertex3f(x + (read->read.size - 1) * view->line_width * view->scale_x, y, 0);
                  glVertex3f(x + (read->read.size) * view->line_width * view->scale_x, y + view->line_height * view->scale_y / 3, 0);
                  glVertex3f(x + (read->read.size) * view->line_width * view->scale_x, y + view->line_height * view->scale_y * 2 / 3, 0);
            glEnd();
      } else if(read->read.dist < 0){
            glBegin(GL_POLYGON);
                  glVertex3f(x + (1) * view->line_width * view->scale_x, y + view->line_height * view->scale_y, 0);
                  glVertex3f(x + (1) * view->line_width * view->scale_x, y, 0);
                  glVertex3f(x, y + view->line_height * view->scale_y / 3, 0);
                  glVertex3f(x, y + view->line_height * view->scale_y * 2 / 3, 0);
            glEnd();
      }
}

void drawRead(ViewPanel *vp, Read *read, float x, float y){
      switch(vp->view->mode){
            case VIEW_MODE_CHARACTER:
                  return drawRead_ch(vp, read, x, y);
            case VIEW_MODE_SQUARE:
                  return drawRead_sq(vp, read, x, y);
            case VIEW_MODE_LINE:
                  return drawRead_li(vp, read, x, y);
      }
}

int selectRead_ch(ViewPanel *vp, Read *read, float x, float y, int id){
      int i;
      for(i=0;i<read->read.size;i++){
            glLoadName(id+i);
            glRectf(x + i * vp->view->font_width, y + vp->view->font_height, x + (i+1) * vp->view->font_width, y);
      }
      return i;
}

int selectRead_sq(ViewPanel *vp, Read *read, float x, float y, int id){
      int i;
      for(i=0;i<read->read.size;i++){
            glLoadName(id+i);
            glRectf(x + i * vp->view->base_width * vp->view->scale_x, y + vp->view->base_height * vp->view->scale_y,
                  x + (i+1) * vp->view->base_width * vp->view->scale_x, y);
      }
      return i;
}

int selectRead_li(ViewPanel *vp, Read *read, float x, float y, int id){
      glLoadName(id);
      glRectf(x , y,
                  x + (read->read.size) * vp->view->line_width * vp->view->scale_x, y  + vp->view->line_height * vp->view->scale_y);
      return 1;
}

int selectRead(ViewPanel *vp, Read *read, float x, float y, int id){
      switch(vp->view->mode){
            case VIEW_MODE_CHARACTER:
                  return selectRead_ch(vp, read, x, y, id);
            case VIEW_MODE_SQUARE:
                  return selectRead_sq(vp, read, x, y, id);
            case VIEW_MODE_LINE:
                  return selectRead_li(vp, read, x, y, id);
            default:
                  return 0;
      }
}

void default_paint(ViewPanel *vp){
      int i, f;
      float x, y;
      int view_layer;
      float layer_offset;
      float font_width, ch_width, line_height;
      View *view;
      Read *read;
      RefSeq *refs;

      glutSetWindow(vp->win_id);
      resetMatrixs(vp);
      view = vp->view;
      glClearColor(0, 0, 0, 0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      switch(view->mode){
            case VIEW_MODE_CHARACTER:
                  font_width  = view->font_width;
                  ch_width    = view->ch_width;
                  line_height = view->font_line_height;
                  break;
            case VIEW_MODE_SQUARE:
                  font_width  = view->base_width * view->scale_x;
                  ch_width    = view->ch_width;
                  line_height = view->base_line_height * view->scale_y;
                  break;
            case VIEW_MODE_LINE:
                  font_width  = view->line_width * view->scale_x;
                  ch_width    = view->ch_width;
                  line_height = view->line_height * view->scale_y;
                  break;
            default:
                  return;
      }

      layer_offset = view->font_line_height + line_height * 2;

      view_layer = (vp->height - layer_offset) / (line_height);

      refs = &(view->refs);
      drawRefSeq(vp, (float)0, (vp->height  - line_height - view->font_line_height), ch_width);
      f = 0;
      if(vp->show_help){
            drawToolTip(vp, vp->width/2 - 100, (vp->height - line_height), "Reference Sequences(maybe null)");
            drawToolTip(vp, vp->width/2 + 100, (vp->height  - line_height - line_height), "Consensus Sequences");
            drawToolTip(vp, 160, vp->status_height + 5, "It is Status Bar");
            f = 0;
      }
      for(i=0;i<refs->cache->size;i++){
            read = refs->cache->reads + refs->cache->offset + i;
            if(read_pos(read->read.pos) > refs->show_start + ch_width) break;
            if(read->y + view->layer_offset < 0) continue;
            if(read->y + view->layer_offset > view_layer) continue;
            x = (read_pos(read->read.pos) - refs->show_start) * font_width;
            y = vp->height - layer_offset - ((read->y + 1 + view->layer_offset)) * line_height;
            if(read_pos(read->read.pos) + read->read.size < refs->show_start) continue;
            drawRead(vp, read, x, y);
            if(!f && x > 0){
                  f = 1;
                  if(vp->show_help){
                        drawToolTip(vp, x + 60, y + line_height, "This is a Read");
                  }
            }
      }
      glutSwapBuffers();
      for(i=0;i<vp->child_size;i++){
            if(vp->childs[i*2] && vp->childs[i*2+1]){
                  ((CHILD_REPAINT)vp->childs[i*2+1])(vp->childs[i*2]);
            }
      }
      vp->paintStatusBar(vp);
}

void default_paintStatusBar(ViewPanel *vp){
      char str[120];
      glutSetWindow(vp->status_id);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glColor3f(1.0, 1.0, 1.0);
      if(vp->view_number){
            num2str(vp->view_number, str);
            sprintf(vp->msg_string, "Input:[%s_]", str);
            drawString(10, 5, vp->msg_string);
      } else if(vp->string_f && vp->string_n){
            sprintf(vp->msg_string, "%s:[%s_]", vp->err_string, vp->view_string);
            drawString(10, 5, vp->msg_string);
      } else if(vp->err){
            drawString(10, 5, vp->err_string);
      } else {
            sprintf(vp->msg_string, "Ref[%s] Position[%ld-%ld] Caching[%ld-%ld] Cacheing seqs[%ld-%ld]", 
                  vp->view->refs.cache->index->mm->ref_name[vp->view->refs.show_id],
                  vp->view->refs.show_start + 1, 
                  vp->view->refs.show_start + (int64_t)vp->view->ch_width + 1, 
                  vp->view->refs.cache->start + 1,
                  vp->view->refs.cache->end + 1,
                  vp->view->refs.cns->start + 1,
                  vp->view->refs.cns->end + 1
                  );
            drawString(10, 5, vp->msg_string);
      }
      if(vp->show_help && !vp->err) vp->show_help = 0;
      glutSwapBuffers();
      glutSetWindow(vp->win_id);
}

#define BUFSIZE 24

int default_pick(ViewPanel *vp, float x, float y, float size, void (*handle)(ViewPanel *vp, SelectObject *obj, int id)){
      GLuint selectBuf[BUFSIZE];
      GLint hits, viewport[4];
      int i, j, id, count;
      int view_layer;
      float font_width, ch_width, line_height;
      float rect[4];
      View *view;
      Read *read;
      RefSeq *refs;
      SelectObject *obj, *root;

      glutSetWindow(vp->win_id);
      view = vp->view;

      switch(view->mode){
            case VIEW_MODE_CHARACTER:
                  font_width  = view->font_width;
                  ch_width    = view->ch_width;
                  line_height = view->font_line_height;
                  break;
            case VIEW_MODE_SQUARE:
                  font_width  = view->base_width * view->scale_x;
                  ch_width    = view->ch_width;
                  line_height = view->base_line_height * view->scale_y;
                  break;
            case VIEW_MODE_LINE:
                  font_width  = view->line_width * view->scale_x;
                  ch_width    = view->ch_width;
                  line_height = view->line_height * view->scale_y;
                  break;
            default:
                  return 0;
      }

      root = NULL;

      glGetIntegerv(GL_VIEWPORT, viewport);
      glSelectBuffer(BUFSIZE, selectBuf);
      glRenderMode(GL_SELECT);

      glInitNames();
      glPushName(0);

      resetPickMatrixs(vp, (GLdouble)x, (GLdouble)(viewport[3] - y), size, viewport);

      rect[0] = x - size/2;
      rect[1] = (float)(vp->height - y) - size/2;
      rect[2] = x + size/2;
      rect[3] = (float)(vp->height + vp->status_height - y) + size/2;

      id = 1;

      view_layer = vp->height / (line_height) - 2;
      if(view_layer < 1) goto END;

      refs = &(view->refs);

      obj = (SelectObject*)malloc(sizeof(SelectObject));
      obj->id_start = id;
      obj->ptr = refs;
      obj->type = SELECT_TYPE_REFSEQ;
      obj->next = NULL;
      root = obj;

      count = selectRefSeq(vp, (float)0, (float)(vp->height - line_height - view->font_line_height),
            ch_width, id);
      id += count;
      obj->id_end = id;

      for(i=0;i<refs->cache->size;i++){
            read = refs->cache->reads + refs->cache->offset + i;
            if(read_pos(read->read.pos) > refs->show_start + ch_width) break;
            if(read->y + view->layer_offset < 0) continue;
            if(read->y + view->layer_offset > view_layer) continue;
            x = (read_pos(read->read.pos) - refs->show_start) * font_width;
            y = vp->height - (2 + (read->y + 1 + view->layer_offset)) * line_height - view->font_line_height;
            if(read_pos(read->read.pos) + read->read.size < refs->show_start) continue;
            if(x + read->read.size * font_width < rect[0] || x > rect[2]) continue;
            if(y + line_height  < rect[1] || y > rect[3]) continue;
            count = selectRead(vp, read, x, y, id);
            if(count > 0){
                  obj->next = (SelectObject*)malloc(sizeof(SelectObject));
                  obj = obj->next;
                  obj->id_start = id;
                  id += count;
                  obj->id_end = id;
                  obj->ptr = read;
                  obj->type = SELECT_TYPE_READ;
                  obj->next = NULL;
            }
      }

      END:
      glFlush();

      hits = glRenderMode(GL_RENDER);
      resetMatrixs(vp);
      if(hits > 0){
            count = 0;
            for(i=0;i<hits;i++){
                  id = selectBuf[count + 3];
                  for(j=1;j<selectBuf[count];j++){
                        if(id < selectBuf[count + 3 + j]) id = selectBuf[count + 3 + j];
                  }
                  count += selectBuf[count] + 3;
            }
            obj = root;
            while(obj != NULL){
                  if(obj->id_start <= id && obj->id_end > id){
                        if(handle) handle(vp, obj, id);
                        break;
                  } else {
                        obj = obj->next;
                  }
            }
      }
      if(root){
            obj = root->next;
            free(root);
            while(obj != NULL){
                  root = obj;
                  obj = root->next;
                  free(root);
            }
      }
      return hits;
}

int print_map(void *obj, maplet *m1){
      int j;
      maqmap_t *m;
      FILE *fpout;
      m = (maqmap_t*)obj;
      fpout = stdout;
      fprintf(fpout, "%s\t%s\t%d\t%c\t%d\t%u\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
                  m1->name, m->ref_name[m1->seqid], (m1->pos>>1) + 1,
                  (m1->pos&1)? '-' : '+', m1->dist, m1->flag, m1->map_qual, (signed char)m1->seq[MAX_READLEN-1],
                  m1->alt_qual, m1->info1&0xf, m1->info2, m1->c[0], m1->c[1], m1->size);
      for (j = 0; j != m1->size; ++j) {
            if (m1->seq[j] == 0) fputc('n', fpout);
            else if ((m1->seq[j]&0x3f) < 27) fputc("acgt"[m1->seq[j]>>6&3], fpout);
            else fputc("ACGT"[m1->seq[j]>>6&3], fpout);
      }
      fputc('\t', fpout);
      for (j = 0; j != m1->size; ++j)
            fputc((m1->seq[j]&0x3f) + 33, fpout);
      fputc('\n', fpout);
      fflush(fpout);
      return 1;
}


void handle_left_pick(ViewPanel *vp, SelectObject *obj, int id){
      RefSeq * refs;
      Read *read;
      switch(obj->type){
            case SELECT_TYPE_NAVIGATION:
                  ((Navigation*)(obj->ptr))->state = 1;
                  return;
            case SELECT_TYPE_REFSEQ:
                  refs = (RefSeq*)obj->ptr;
                  id = id - obj->id_start;
                  if(refs->tooltips[id] & 1){
                        refs->tooltips[id] &= ~0x01;
                        notifyView(vp->view, VIEW_EVENT_MARK_REF, refs->show_start + id, 0);
                  } else {
                        refs->tooltips[id] |= 0x01;
                        notifyView(vp->view, VIEW_EVENT_MARK_REF, refs->show_start + id, 1);
                  }
                  return;
            case SELECT_TYPE_READ:
                  read = (Read*)obj->ptr;
                  print_map(vp->view->refs.cache->index->mm, &(read->read));
                  id = id - obj->id_start;
                  (read->flag & READ_SELECT)? (read->flag &= ~READ_SELECT) : (read->flag |= READ_SELECT);
                  if(read->read.dist) notifyView(vp->view, VIEW_EVENT_SELECT_READ, read->read.dist>0? read_pos(read->read.pos):read_pos(read->read.pos)+read->read.size, read->read.dist);
                  return;
      }
}

void handle_right_pick(ViewPanel *vp, SelectObject *obj, int id){
      RefSeq * refs;
      Read *read;
      switch(obj->type){
            case SELECT_TYPE_REFSEQ:
                  refs = (RefSeq*)obj->ptr;
                  id = id - obj->id_start;
                  if(refs->tooltips[id] & 0x02){
                        refs->tooltips[id] &= ~(0x02);
                        notifyView(vp->view, VIEW_EVENT_MARK_COL, refs->show_start + id, 0);
                  } else {
                        refs->tooltips[id] |= 0x02;
                        notifyView(vp->view, VIEW_EVENT_MARK_COL, refs->show_start + id, 1);
                  }
                  return;
            case SELECT_TYPE_READ:
                  read = (Read*)obj->ptr;
                  id = id - obj->id_start;
                  (read->flag & READ_SHOWTIP)? (read->flag &= ~READ_SHOWTIP) : (read->flag |= READ_SHOWTIP);
                  return;
      }
}

void handle_mouse_over(ViewPanel *vp, SelectObject *obj, int id){
      RefSeq * refs;
      Read *read;
      Navigation *nav;
      int q;
      char ch;
      switch(obj->type){
            case SELECT_TYPE_NAVIGATION:
                  nav = (Navigation*)(obj->ptr);
                  sprintf(vp->err_string, "Drag navigation to move left/right");
                  return;
            case SELECT_TYPE_REFSEQ:
                  refs = (RefSeq*)obj->ptr;
                  id = id - obj->id_start;
                  sprintf(vp->err_string, "Refs[%s] %ld", refs->cache->index->mm->ref_name[refs->show_id], refs->show_start + id + 1);
                  return;
            case SELECT_TYPE_READ:
                  read = (Read*)obj->ptr;
                  id = id - obj->id_start;
                  q = read->read.seq[id] & 0x3f;
                  switch(vp->view->mode){
                        case VIEW_MODE_CHARACTER:
                        case VIEW_MODE_SQUARE:
                              if (read->read.seq[id] == 0) ch = 'n';
                              else if (q < 27) ch = acgt[read->read.seq[id]>>6&3];
                              else ch = ACGT[read->read.seq[id]>>6&3];
                              sprintf(vp->err_string, "Read: %ld|%c|%s[%d]|%c %d", read_pos(read->read.pos) + 1, 
                                    read_strand(read->read.pos)? '-':'+', read->read.name, id + 1, ch, q);
                              return;
                        case VIEW_MODE_LINE:
                              sprintf(vp->err_string, "Read: %ld|%c|%s", read_pos(read->read.pos) + 1, 
                                    read_strand(read->read.pos)? '-':'+', read->read.name);
                              return;
                  }
      }
}

void default_mousePressed(ViewPanel *vp, int button, int x, int y){
      glutSetWindow(vp->win_id);
      if(button == GLUT_RIGHT_BUTTON){
            if(vp->pick && vp->handle_right_pick
                  && vp->pick(vp, x, y, 1, vp->handle_right_pick)){
            } else {    
                  vp->err = 1;
                  sprintf(vp->err_string, "enter '?' to get help");
                  vp->show_help = 1;
            }
            glutSetCursor(GLUT_CURSOR_CROSSHAIR);
            glutPostRedisplay();
            return;
      }
      if(button == GLUT_MIDDLE_BUTTON){
            vp->view->state = 1;
            vp->view->last_x = x;
            vp->view->last_y = y;
            vp->view->old_x  = vp->view->refs.show_start;
            vp->view->old_y  = vp->view->layer_offset;
            return;
      }
      vp->view->selecting = 1;
      if(vp->pick && vp->handle_left_pick && vp->pick(vp, x, y, 1, vp->handle_left_pick)){
      } else {    
            vp->err = 1;
            sprintf(vp->err_string, "enter '?' to get help");
            vp->show_help = 1;
      }
      glutSetCursor(GLUT_CURSOR_CROSSHAIR);
      glutPostRedisplay();
}

void default_mouseReleased(ViewPanel *vp, int button, int x, int y){
      if(vp->msg) return;
      glutSetWindow(vp->win_id);
      if(button == GLUT_RIGHT_BUTTON){
            glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
            return;
      }
      if(button == GLUT_MIDDLE_BUTTON){
            vp->view->state = 0;
            vp->view->refs.show_start = vp->view->old_x;
            vp->view->layer_offset = vp->view->old_y;
            glutPostRedisplay();
            return;
      }
      glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
      vp->view->selecting = 0;
      if(vp->view->nav.state){
            vp->view->nav.arrow_x = vp->view->nav.center_x;
            vp->view->nav.arrow_y = vp->view->nav.center_y;
            vp->view->nav.state = 0;
      }
      glutPostRedisplay();
}

void default_mouseDragged(ViewPanel *vp, int x, int y){
      if(vp->view == NULL) return;
      if(vp->msg) return;
      glutSetWindow(vp->win_id);
      if(vp->view->state){
            vp->view->layer_offset = vp->view->old_y + (y - vp->view->last_y) / vp->view->font_line_height;
            vp->view->refs.show_start = vp->view->old_x - (x - vp->view->last_x) / vp->view->font_width;
            glutPostRedisplay();
      }
}

void default_mouseMoved(ViewPanel *vp, int x, int y){
      if(vp->msg) return;
      glutSetWindow(vp->win_id);
      vp->_x = x;
      vp->_y = y;
      if(vp->pick){
            if(vp->handle_mouse_over && vp->pick(vp, x, y, 1, vp->handle_mouse_over)){
                  vp->err = 1;
            } else {
                  vp->err = 0;
            }
            vp->paintStatusBar(vp);
      }
      glutPostRedisplay();
}

static void select_ref(void *obj, int val){
      ViewPanel *vp;
      vp = ((GList*)obj)->window.parent;
      if(val != vp->view->refs.show_id){
            view_goto(vp->view, val, 1);
            vp->paint(vp);
      }
}

void default_mouseWheel(ViewPanel *vp, int wheel, int direction, int x, int y){
      if(vp->view->mode == VIEW_MODE_CHARACTER) return;
      if(vp->msg) return;
      if(direction > 0){
            vp->view->scale_x *= 1.2;
            vp->view->scale_y *= 1.2;
      } else if(vp->view->scale_x > 0.33){
            vp->view->scale_x /= 1.2;
            vp->view->scale_y /= 1.2;
      }
      vp->view->ch_width = vp->width/(vp->view->base_width * vp->view->scale_x);
      glutPostRedisplay();
}

void default_keyTyped(ViewPanel *vp, unsigned char key, int x, int y){
      View *view;
      int cell_w, cell_h, n_disp;
      int i;
      int64_t t;
      int modifiers, multiple;
      glutSetWindow(vp->win_id);
      modifiers = glutGetModifiers();
      if(modifiers & GLUT_ACTIVE_SHIFT){
            multiple = 100;
      } else if(modifiers & GLUT_ACTIVE_CTRL){
            multiple = 1000;
      } else {
            multiple = 1;
      }
      if(vp->msg){
            if(key != 13 && key != 27) return;
            showSubWindows();
            vp->msg = 0;
            glutPostRedisplay();
            return;
      }
      if(!vp->string_f && key == '?'){
            vp->msg = 1;
            hideSubWindows();
            glutPostRedisplay();
            return;
      }
      if(vp->view == NULL) return;
      if(vp->string_f){
            if(key == 27){
                  vp->string_f = 0;
                  vp->string_n = 0;
                  vp->view_string[0] = '\0';
                  vp->err = 0;
            } else if(key == 13){
                  switch(vp->command){
                        case VP_CMD_OPEN:
                              view = createView(vp->view_string, NULL, vp->width, vp->height, 0);
                              if(view == NULL){
                                    vp->err = 1;
                                    sprintf(vp->err_string, "Cannot open view %s", vp->view_string);
                              } else {
                                    closeView(vp->view);
                                    vp->view = view;
                                    vp->err = 1;
                                    sprintf(vp->err_string, "set view to %s", vp->view_string);
                                    vp->view_string[0] = '\0';
                                    vp->string_f = 0;
                                    vp->string_n = 0;
                                    goto REFRESH;
                              }
                              break;
                        case VP_CMD_CMD:
                              vp->err = 0;
                              execute_cmd(vp, vp->view_string);
                              break;
                  }
                  vp->view_string[0] = '\0';
                  vp->string_f = 0;
                  vp->string_n = 0;
            } else if(key == '\b'){
                  if(!vp->string_n) return;
                  vp->string_n --;
                  vp->view_string[vp->string_n] = '\0';
            } else {
                  vp->view_string[vp->string_n++] = key;
                  vp->view_string[vp->string_n] = '\0';
            }
            glutPostRedisplay();
            return;
      } else if(key >= '0' && key <= '9'){
            if(key == '0' && vp->view_number == 0){
                  vp->view->scale_x = 1;
                  vp->view->scale_y = 1;
                  if(vp->view->mode != VIEW_MODE_CHARACTER) vp->view->ch_width = vp->width / vp->view->base_width;
            } else {
                  vp->view_number = vp->view_number * 10 + key - '0';
            }
            glutPostRedisplay();
            return;
      } else if(key == 13){
            if(vp->view_number){
                  vp->view->rolling = 0;
                  view_goto(vp->view, vp->view->refs.show_id, vp->view_number - 1);
                  vp->err = 1;
                  sprintf(vp->err_string, "goto: %ld", vp->view_number);
                  vp->view_number = 0;
            } else {
                  vp->err = 0;
                  if(vp->view->rolling) vp->view->rolling = 0;
                  else {
                        vp->view->rolling = vp->view->step;
                        if(vp->timer) vp->timer(vp, glutGetWindow());
                  }
            }
            glutPostRedisplay();
            return;
      } else if(key == 2){
            if(vp->view_number){
                  vp->view_number /= 10;
                  glutPostRedisplay();
                  return;
            }
            if(vp->view->rolling) vp->view->rolling = 0;
            else {
                  vp->view->rolling = -vp->view->step;
                  if(vp->timer) vp->timer(vp, glutGetWindow());
            }
            return;
      }

//    for(i=0;i<TOOLTIP_SIZE;i++) vp->view->refs.tooltips[i] &= ~(0x02);
      
      if(vp->view_number > 0){
            if(key == 27){
                  vp->view_number = 0;
                  glutPostRedisplay();
                  return;
            } else {
                  vp->view->step = vp->view_number;
            }
      }
      vp->view_number = 0;

      switch(key){
            case 'f':
                  glutSetWindow(vp->parent_win_id);
                  glutFullScreen();
                  glutSetWindow(vp->win_id);
                  break;
            case 'q':
                  if (vp->global_flag & GF_HIDE_MAPQ) {
                        vp->global_flag &= ~GF_HIDE_MAPQ;
                        vp->err = 1;
                        sprintf(vp->err_string, "hide mapping qualities");
                  } else {
                        vp->global_flag |= GF_HIDE_MAPQ;
                        vp->err = 1;
                        sprintf(vp->err_string, "show mapping qualities");
                  }
                  glutPostRedisplay();
                  break;
            case 'e':
                  vp->global_flag &= ~GF_HIDE_MAPQ;
                  if (vp->global_flag & GF_IS_SINGLEQ) {
                        vp->global_flag &= ~GF_IS_SINGLEQ;
                        vp->err = 1;
                        sprintf(vp->err_string, "visualize paired-end mapping qualities");
                  } else {
                        vp->global_flag |= GF_IS_SINGLEQ;
                        vp->err = 1;
                        sprintf(vp->err_string, "visualize single-end mapping qualities");
                  }
                  glutPostRedisplay();
                  break;            
            case 27:
                  exit(0);
            case 'o':
                  vp->command = VP_CMD_OPEN;
                  vp->string_f = 1;
                  vp->string_n = 0;
                  vp->view_string[0] = '\0';
                  vp->err = 1;
                  sprintf(vp->err_string, "try open new view, please input filename");
                  glutPostRedisplay();
                  break;
            case 'c':
                  vp->command = VP_CMD_CMD;
                  vp->string_f = 1;
                  vp->string_n = 0;
                  vp->view_string[0] = '\0';
                  vp->err = 1;
                  sprintf(vp->err_string, "input command");
                  glutPostRedisplay();
                  break;
            case '=':
            case '+':
                  if(modifiers & GLUT_ACTIVE_CTRL){
                        if(vp->view->map_file){
                              addViewPanel(NULL, vp->view->map_file, vp->view->cns_file, vp->view->style);
                              glutSetWindow(vp->win_id);
                        }
                        break;
                  }
                  if(vp->view->mode == VIEW_MODE_CHARACTER){
                        vp->err = 1;
                        sprintf(vp->err_string, "Cannot zoom in in character mode");
                  } else {
                        vp->view->scale_x *= 1.2;
                        vp->view->scale_y *= 1.2;
                        switch(vp->view->mode){
                              case VIEW_MODE_SQUARE:
                                    vp->view->ch_width = vp->width/(vp->view->base_width * vp->view->scale_x);
                                    break;
                              case VIEW_MODE_LINE:
                                    vp->view->ch_width = vp->width/(vp->view->line_width * vp->view->scale_x);
                                    break;
                        }
                  }
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start);
                  glutPostRedisplay();
                  break;
            case 31: removeViewPanel(vp); break; /* for Mac OS X */
            case '-':
                  if(modifiers & GLUT_ACTIVE_CTRL){
                        removeViewPanel(vp);
                        break;
                  }
                  if(vp->view->mode == VIEW_MODE_CHARACTER){
                        vp->err = 1;
                        sprintf(vp->err_string, "Cannot zoom out in character mode");
                  } else if(vp->view->scale_x > 0.33){
                        vp->view->scale_x /= 1.2;
                        vp->view->scale_y /= 1.2;
                        switch(vp->view->mode){
                              case VIEW_MODE_SQUARE:
                                    vp->view->ch_width = vp->width/(vp->view->base_width * vp->view->scale_x);
                                    break;
                              case VIEW_MODE_LINE:
                                    vp->view->ch_width = vp->width/(vp->view->line_width * vp->view->scale_x);
                                    break;
                        }
                  }
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start);
                  glutPostRedisplay();
                  break;
            case 'r':
                  if(vp->ref_menu){
                        freeGList(vp->ref_menu);
                        vp->ref_menu = NULL;
                  } else {
                        cell_w = 100;
                        cell_h = 20;
                        n_disp = vp->view->refs.cache->index->mm->n_ref;
                        if(n_disp * cell_h > vp->height - vp->status_height){
                              n_disp = (vp->height - vp->status_height) / cell_h;
                        }
                        vp->ref_menu = createGList(0, vp, 5, vp->height - (n_disp * cell_h), cell_w, cell_h, n_disp);
                        for(i=0;i<vp->view->refs.cache->index->mm->n_ref;i++){
                              GList_addOption(vp->ref_menu, vp->view->refs.cache->index->mm->ref_name[i]);
                        }
                        vp->ref_menu->valueChanged = select_ref;
                  }
                  glutPostRedisplay();
                  break;
                  vp->err = 1;
                  sprintf(vp->err_string, "Refresh");
                  REFRESH:
                  vp->view->refs.cache->offset = 0;
                  vp->view->refs.cache->size   = 0;
                  vp->view->refs.cache->start = 0;
                  vp->view->refs.cache->end   = 0;
                  vp->view->refs.cns->ref_id  = -1;
                  t = vp->view->refs.show_start;
                  vp->view->refs.show_start = t + 1;
                  view_goto(vp->view, vp->view->refs.show_id, t);
                  glutPostRedisplay();
          case 8:
          case 'H':
          case 'h':
                  vp->err = 0;
                  if (key == 8) multiple = 1000;
                  else if (key == 'H') multiple = 100;
                  if(vp->view->refs.show_start > 0){
                        view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start - vp->view->step * multiple);
                        glutPostRedisplay();
                  }
                  break;
          case 12:
          case 'L':
          case 'l':
                  vp->err = 0;
                  if (key == 12) multiple = 1000;
                  else if (key == 'L') multiple = 100;
                  if(vp->view->refs.show_start < vp->view->refs.cache->length){
                        view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start + vp->view->step * multiple);
                        glutPostRedisplay();
                  }
                  break;
          case 'k':
                  vp->err = 1;
                  vp->view->layer_offset += multiple;
                  if(vp->view->layer_offset > 2) vp->view->layer_offset = 2;
                  sprintf(vp->err_string, "move view offset to %d line", vp->view->layer_offset);
                  glutPostRedisplay();
                  break;
          case 'j':
                  vp->err = 1;
                  vp->view->layer_offset -= multiple;
                  sprintf(vp->err_string, "move view offset to %d line", vp->view->layer_offset);
                  glutPostRedisplay();
                  break;
            case ' ':
                  vp->err = 0;
                  if(vp->view->refs.show_start < vp->view->refs.cache->length){
                        view_goto(vp->view, vp->view->refs.show_id,
                              vp->view->refs.show_start + 
                              vp->view->ch_width);
                        glutPostRedisplay();
                  }
                  break;
            case 'u':
                  vp->err = 0;
                  if(vp->view->refs.show_start > 0){
                        view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start - vp->view->ch_width);
                        glutPostRedisplay();
                  }
                  break;
            case 'g':
                  view_goto(vp->view, vp->view->refs.show_id, 0);
                  vp->err = 1;
                  sprintf(vp->err_string, "goto begin");
                  glutPostRedisplay();
                  break;
            case 'G':
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.cache->length);
                  vp->err = 1;
                  sprintf(vp->err_string, "goto end");
                  glutPostRedisplay();
                  break;
            case '>':
                  vp->err = 0;
                  t = vp->view->refs.show_start;
                  while(1){
                        for(i=0;i<vp->view->refs.cache->size;i++){
                              if(read_pos(vp->view->refs.cache->reads[vp->view->refs.cache->offset + i].read.pos) > t){
                                    view_goto(vp->view, vp->view->refs.show_id, 
                                          read_pos(vp->view->refs.cache->reads[vp->view->refs.cache->offset + i].read.pos));
                                    glutPostRedisplay();
                                    return;
                              }
                        }
                        if(vp->view->refs.show_start + vp->view->ch_width < vp->view->refs.cache->length
                                    && view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.cache->end + 1) 
                                    && vp->view->refs.cache->size){
                        } else {
                              vp->err = 1;
                              sprintf(vp->err_string, "No more read available");
                              glutPostRedisplay();
                              return;
                        }
                  }
                  break;
            case '<':
                  vp->err = 0;
                  t = vp->view->refs.show_start;
                  while(1){
                        for(i=vp->view->refs.cache->size-1;i>=0;i--){
                              if(read_pos(vp->view->refs.cache->reads[vp->view->refs.cache->offset + i].read.pos) < t){
                                    view_goto(vp->view, vp->view->refs.show_id, 
                                          read_pos(vp->view->refs.cache->reads[vp->view->refs.cache->offset + i].read.pos));
                                    glutPostRedisplay();
                                    return;
                              }
                        }
                        if(vp->view->refs.show_start > 0 && 
                                    view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.cache->start - vp->view->ch_width)){
                        } else {
                              vp->err = 1;
                              sprintf(vp->err_string, "No more read available");
                              glutPostRedisplay();
                              return;
                        }
                  }
                  break;
            case 'n':
                  vp->err = 1;
                  if(vp->view->refs.cache->index->mm->n_ref > 1){
                        i = (vp->view->refs.show_id + 1) % vp->view->refs.cache->index->mm->n_ref;
                        view_goto(vp->view, i, 0);
                        sprintf(vp->err_string, "Switch to ref seq [%s]", vp->view->refs.cache->index->mm->ref_name[i]);
                  } else {
                        sprintf(vp->err_string, "Cannot switch: only one ref seq [%s]", 
                              vp->view->refs.cache->index->mm->ref_name[vp->view->refs.show_id]);
                  }
                  glutPostRedisplay();
                  break;
            case 'p':
                  vp->err = 1;
                  if(vp->view->refs.cache->index->mm->n_ref > 1){
                        i = (vp->view->refs.show_id - 1 + vp->view->refs.cache->index->mm->n_ref) % vp->view->refs.cache->index->mm->n_ref;
                        view_goto(vp->view, i, 0);
                        sprintf(vp->err_string, "Switch to ref seq [%s]", vp->view->refs.cache->index->mm->ref_name[i]);
//                      if(view_goto(vp->view, i, 0)){
//                      } else {
//                            sprintf(err_string, "Cannot switch to ref seq [%s]", vp->view->refs.index->mm->ref_name[i]);
//                      }
                  } else {
                        sprintf(vp->err_string, "Cannot switch: only one ref seq [%s]",
                              vp->view->refs.cache->index->mm->ref_name[vp->view->refs.show_id]);
                  }
                  glutPostRedisplay();
                  break;
            default:
                  vp->err = 1;
                  sprintf(vp->err_string, "unknown key binding: %d[%c]", key, key);
                  glutPostRedisplay();
      }
}

void default_specialKey(ViewPanel *vp, int key, int x, int y){
      if(!vp->view) return;
      glutSetWindow(vp->win_id);
      switch(key){
            case GLUT_KEY_F1:
                  vp->view->mode = VIEW_MODE_CHARACTER;
                  vp->view->ch_width = vp->width/vp->view->font_width;
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start);
                  glutPostRedisplay();
                  return;
            case GLUT_KEY_F2:
                  vp->view->mode = VIEW_MODE_SQUARE;
                  vp->view->ch_width = vp->width/(vp->view->base_width * vp->view->scale_x);
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start);
                  glutPostRedisplay();
                  return;
            case GLUT_KEY_F3:
                  vp->view->mode = VIEW_MODE_LINE;
                  vp->view->ch_width = vp->width/(vp->view->line_width * vp->view->scale_x);
                  view_goto(vp->view, vp->view->refs.show_id, vp->view->refs.show_start);
                  glutPostRedisplay();
                  return;
            case GLUT_KEY_LEFT:
                  return default_keyTyped(vp, 'h', x, y);
            case GLUT_KEY_RIGHT:
                  return default_keyTyped(vp, 'l', x, y);
            case GLUT_KEY_UP:
                  return default_keyTyped(vp, 'k', x, y);
            case GLUT_KEY_DOWN:
                  return default_keyTyped(vp, 'j', x, y);
            case GLUT_KEY_PAGE_UP:
                  return default_keyTyped(vp, 'u', x, y);
            case GLUT_KEY_PAGE_DOWN:
                  return default_keyTyped(vp, ' ', x, y);
            case GLUT_KEY_HOME:
                  return default_keyTyped(vp, 'g', x, y);
            case GLUT_KEY_END:
                  return default_keyTyped(vp, 'G', x, y);
      }
}
ViewPanel* createViewPanel(int pw_id, View *view, float off_x, float off_y, float width, float height){
      int win_id;
      int status_height;
      ViewPanel *vp;
      status_height = 20;


      win_id = glutCreateSubWindow(pw_id, off_x, off_y, width, height);
      glClearColor(0, 0, 0, 0);
      glEnable(GL_DEPTH_TEST);
      vp = (ViewPanel*)malloc(sizeof(ViewPanel));
      vp->parent_win_id = pw_id;
      vp->win_id = win_id;
      vp->status_id = glutCreateSubWindow(win_id, 0, height - status_height, width, status_height);
      glClearColor(0.2, 0.2, 0.2, 0);
      glEnable(GL_DEPTH_TEST);
      glutDisplayFunc(display_bar);
      glutReshapeFunc(bar_resize);
      vp->off_x  = off_x;
      vp->off_y  = off_y;
      vp->width  = width;
      vp->height = height - status_height;
      vp->status_width  = width;
      vp->status_height = status_height;


      vp->view   = view;

      vp->view_number = 0;
      vp->string_f    = 0;
      vp->string_n    = 0;

      vp->err = 0;
      vp->msg = 0;

      vp->show_help = 0;

      vp->interval = 180;

      vp->command = 0;

      vp->_x  = 0;
      vp->_x1 = 0;
      vp->_x2 = 0;
      vp->_y  = 0;
      vp->_y1 = 0;
      vp->_y2 = 0;

      vp->global_flag = 0;

      vp->resize = (void*)default_resize;
      vp->paint  = (void*)default_paint;
      vp->pick   = (void*)default_pick;
      vp->paintStatusBar    = (void*)default_paintStatusBar;
      vp->handle_left_pick  = (void*)handle_left_pick;
      vp->handle_right_pick = (void*)handle_right_pick;
      vp->handle_mouse_over = (void*)handle_mouse_over;
      vp->mousePressed  = (void*)default_mousePressed;
      vp->mouseReleased = (void*)default_mouseReleased;
      vp->mouseDragged  = (void*)default_mouseDragged;
      vp->mouseMoved    = (void*)default_mouseMoved;
      vp->mouseWheel    = (void*)default_mouseWheel;
      vp->keyTyped      = (void*)default_keyTyped;
      vp->specialKey    = (void*)default_specialKey;
      vp->timer         = (void*)default_timer;
      vp->synchronize   = (void*)synchronize;

      vp->owner = NULL;

      vp->childs = NULL;
      vp->child_size = 0;
      vp->child_capacity = 0;

      vp->ref_menu = NULL;

      register_window(vp->win_id, vp, WINDOW_TYPE_VIEWPANEL);

      glutSetWindow(vp->win_id);
      glutReshapeFunc(reshape);
      glutDisplayFunc(display);
      glutMouseFunc(mouse);
      glutMotionFunc(motion);
      glutPassiveMotionFunc(mouse_move);
      glutKeyboardFunc(keyboard);
      glutSpecialFunc(special_key);
#ifdef HAVE_FREEGLUT
      glutMouseWheelFunc(mouse_wheel);
#endif

      vp->resize(vp, width, height);
      view_resize(view, vp->width, vp->height);

      return vp;
}

void closeViewPanel(ViewPanel *vp){
      int i;
      closeView(vp->view);
      glutDestroyWindow(vp->status_id);
      glutDestroyWindow(vp->win_id);
      if(vps_size >= vp->win_id && vps[vp->win_id-1] == vp){
            vps[vp->win_id-1] = NULL;
      }
      for(i=0;i<vps_size;i++){
            if(vps[i] && vp_types[i] == WINDOW_TYPE_VIEWPANEL) removeObserverView(((ViewPanel*)vps[i])->view, vp);
      }
      free(vp);
}

void closeViewPanels(){
      int i;
      for(i=0;i<vps_size;i++){
            if(vps[i] && vp_types[i] == WINDOW_TYPE_VIEWPANEL){
                  closeViewPanel((ViewPanel*)vps[i]);
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index