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

adisplay.cpp

/*
    Aeskulap - DICOM image viewer and network client
    Copyright (C) 2005  Alexander Pipelka

    This file is part of Aeskulap.

    Aeskulap is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Aeskulap is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Aeskulap; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Alexander Pipelka
    pipelka@teleweb.at

    Last Update:      $Author: braindead $
    Update Date:      $Date: 2006/03/16 15:11:19 $
    Source File:      $Source: /sources/aeskulap/aeskulap/widgets/adisplay.cpp,v $
    CVS/RCS Revision: $Revision: 1.20 $
    Status:           $State: Exp $
*/

#include <iostream>
#include <cmath>

#include "adisplay.h"
#include "poolstudy.h"
#include "aiconfactory.h"
#include "gettext.h"

namespace Aeskulap {

Display::Display() : SimpleDisplay(),
m_drag_active(false),
m_cursor_pan(NULL),
m_cursor_windowlevel(NULL),
m_cursor_zoom(NULL), 
m_mouse_functions(true)
{
      set_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK);
}

Display::Display(const Glib::RefPtr<DisplayParameters>& params) : SimpleDisplay(params) ,
m_cursor_pan(NULL),
m_cursor_windowlevel(NULL),
m_cursor_zoom(NULL)
{
      set_events(Gdk::BUTTON_PRESS_MASK);
}

Display::~Display() {
      delete m_cursor_pan;
      delete m_cursor_windowlevel;
      delete m_cursor_zoom;

}

void Display::on_realize() {
      SimpleDisplay::on_realize();

      m_fntdesc.set_family("sans");

      Glib::RefPtr<Gdk::Pixbuf> p;
      p = Aeskulap::IconFactory::load_from_file("cursor_pan.png");
      if(p) {
            m_cursor_pan = new Gdk::Cursor(
                                    Gdk::Display::get_default(),
                                    p,
                                    11, 11);
      }
      
      p = Aeskulap::IconFactory::load_from_file("cursor_windowlevel.png");
      if(p) {
            m_cursor_windowlevel = new Gdk::Cursor(
                                    Gdk::Display::get_default(),
                                    p,
                                    11, 11);
      }
      
      p = Aeskulap::IconFactory::load_from_file("cursor_zoom.png");
      if(p) {
            m_cursor_zoom = new Gdk::Cursor(
                                    Gdk::Display::get_default(),
                                    p,
                                    11, 11);
      }

      p = Aeskulap::IconFactory::load_from_file("start-here.png");
      if(p) {
            m_cursor_locate = new Gdk::Cursor(
                                    Gdk::Display::get_default(),
                                    p,
                                    8, 8);
      }

      m_changed = false;

      m_drag_active = false;
      m_drag_button = 0;
      m_drag_start_x = 0;
      m_drag_start_y = 0;

      m_colorSelected = Gdk::Color("green");
      m_colorSeriesSelected = Gdk::Color("orange");
      m_colorFrame  = Gdk::Color("white");
      m_colorText = Gdk::Color("white");
      m_colorReferenceCurrent = Gdk::Color("orange");
      m_colorReference = Gdk::Color("grey");

      m_colormap->alloc_color(m_colorSelected);
      m_colormap->alloc_color(m_colorSeriesSelected);
      m_colormap->alloc_color(m_colorFrame);
      m_colormap->alloc_color(m_colorText);
      m_colormap->alloc_color(m_colorReferenceCurrent);
      m_colormap->alloc_color(m_colorReference);

      m_layoutL = Pango::Layout::create(m_pangoctx);
      m_layoutL->set_alignment(Pango::ALIGN_LEFT);

      m_layoutR = Pango::Layout::create(m_pangoctx);
      m_layoutR->set_alignment(Pango::ALIGN_RIGHT);

      m_layoutB = Pango::Layout::create(m_pangoctx);
      m_layoutB->set_alignment(Pango::ALIGN_LEFT);
}

bool Display::on_expose_event(GdkEventExpose* event) {
      if(!SimpleDisplay::on_expose_event(event)) {
            return false;
      }

      m_GC->set_foreground(m_colorFrame);

      if(m_disp_params && m_disp_params->selected) {
            m_GC->set_foreground(m_colorSelected);
            m_window->draw_rectangle(m_GC, false, 2, 2, get_width()-5, get_height()-5);
      }
      else if(m_disp_params && m_disp_params->series_selected) {
            m_GC->set_foreground(m_colorSeriesSelected);
      }

      m_window->draw_rectangle(m_GC, false, 1, 1, get_width()-3, get_height()-3);

      if(m_image && !m_playing) {
            m_GC->set_foreground(m_colorText);
      
            m_GC->set_background(m_colorText);
            m_fntdesc.set_size((get_width() * 12 * PANGO_SCALE) / 1280 + 2 * PANGO_SCALE);
            Glib::ustring text = m_image->series()->institutionname() + "\n";
            text += m_image->study()->patientsname() + "\n";
            text += m_image->study()->patientsbirthdate() + " " + m_image->study()->patientssex() + "\n";
            text += gettext("Acc:\n");
            text += m_image->date() + "\n";
            text += gettext("Acq Tm: ") + m_image->time() + "\n";
            text += "\n";
            
            char buffer[50];
            g_snprintf(buffer, sizeof(buffer), "%i x %i", m_image->width(), m_image->height());

            text += buffer;
            
            m_layoutR->set_font_description(m_fntdesc);
            m_layoutR->set_text(text);
            m_layoutR->set_width((get_width()/2 - m_offset_right) * PANGO_SCALE);
            
            text = m_image->model() + "\n";
            g_snprintf(buffer, sizeof(buffer), gettext("Image: %i / %i"), m_image->get_index(), m_image->series()->size());
            text += buffer;
      
            m_layoutL->set_font_description(m_fntdesc);
            m_layoutL->set_text(text);
            m_layoutL->set_width((get_width()/2 - m_offset_left) * PANGO_SCALE);

            g_snprintf(buffer, sizeof(buffer), "C: %i\nW: %i", m_disp_params->window.center, m_disp_params->window.width);

            text = buffer;

            m_layoutB->set_font_description(m_fntdesc);
            m_layoutB->set_text(text);
            m_layoutB->set_width((get_width()/2 - m_offset_left) * PANGO_SCALE);
            int sw = 0;
            int sh = 0;
            m_layoutB->get_pixel_size(sw, sh);
            
            m_window->draw_layout(m_GC, m_offset_left, 5, m_layoutL);
            m_window->draw_layout(m_GC, get_width()/2, 5, m_layoutR);
            m_window->draw_layout(m_GC, m_offset_left, get_height()-5-sh, m_layoutB);

            draw_ruler_v();
            draw_ruler_h();
      }

      signal_draw(this, m_window, m_GC);

      return true;
}

void Display::bitstretch(bool smooth) {
      if(m_drag_active && smooth) {
            return;
      }

      Aeskulap::SimpleDisplay::bitstretch(smooth);
}

bool Display::on_button_press_event(GdkEventButton* button) {
      if(!m_mouse_functions) {
            signal_button(button, true);
            return true;
      }

      if(m_drag_active) {
            return false;
      }

      if(!m_disp_params) {
            return false;
      }
      
      if(button->type == GDK_2BUTTON_PRESS) {
            while(Gtk::Main::events_pending()) Gtk::Main::iteration(false);
            signal_doubleclick(this);
            return true;
      }

      if(button->button == 1 && button->state & GDK_SHIFT_MASK) {
            get_window()->set_cursor(*m_cursor_locate);
            m_drag_start_y = button->y;
            m_drag_button = 1;
            add_modal_grab();
            return true;
      }
      else if(button->button == 1) {
            //m_drag_active = true;
            m_drag_button = 1;
            m_drag_start_x = button->x;
            m_drag_start_y = button->y;
            m_drag_window = m_disp_params->window;

            //get_window()->set_cursor(*m_cursor_windowlevel);
            add_modal_grab();
            return true;
      }

      if(button->button == 2) {
            m_drag_active = true;
            m_drag_button = 2;
            m_drag_start_x = 0;
            m_drag_start_y = button->y;

            get_window()->set_cursor(*m_cursor_zoom);
            add_modal_grab();
            return true;
      }

      if(button->button == 3) {
            if(button->state & GDK_CONTROL_MASK) {
                  signal_popup(button);
                  return true;
            }
            else {
                  m_drag_active = true;
                  m_drag_button = 3;
                  m_drag_start_x = button->x;
                  m_drag_start_y = button->y;
      
                  get_window()->set_cursor(*m_cursor_pan);
                  add_modal_grab();
                  return true;
            }
      }

      return false;
}

bool Display::on_button_release_event(GdkEventButton* button) {

      Gtk::EventBox::on_button_release_event(button);

      if(m_image && !m_disp_params->selected) {
            m_disp_params->selected = true;
            signal_selected(get_id());
      }

      if(!m_mouse_functions) {
            signal_button(button, false);
            return true;
      }

      if(!m_disp_params) {
            return false;
      }
      
      get_window()->set_cursor();
      remove_modal_grab();

      /*if(!m_drag_active) {
            return false;
      }*/

      m_drag_active = false;
      m_drag_button = 0;
      
      if(m_changed && !m_playing) {
            signal_changed(get_id(), true);

            bitstretch(true);
            queue_draw();
      }
      m_changed = false;

      return true;
}

bool Display::on_motion_notify_event(GdkEventMotion* event) {
      static bool block = false;

      if(!m_disp_params || !m_image) {
            return false;
      }

      if(!m_mouse_functions || (!m_drag_active && !block)) {
            signal_motion(event);
      }

      int x,y;
      get_pointer(x, y);
      
      if(m_drag_button == 1 && event->state & GDK_SHIFT_MASK) {
            int diff = (int)(y - m_drag_start_y);
            signal_locate(diff);
            m_drag_start_y = y;
            return true;
            
      }

      if(m_drag_button == 1 && !m_drag_active) {
            double d = sqrt(pow(x - m_drag_start_x, 2) + pow(y - m_drag_start_y, 2));
            if(d > 4) {
                  m_drag_active = true;
                  get_window()->set_cursor(*m_cursor_windowlevel);
            }
      }
      
      if(!m_drag_active || block) {
            return true;
      }

      if(m_drag_button == 1) {
            set_window_palette(x, y);
            update();
      }

      if(m_drag_button == 2) {
            gdouble dy = m_drag_start_y - y;

            int wo,ho;
            get_zoom_wh(wo, ho);

            int dxm = wo/2 + m_disp_params->move_x;
            int dym = ho/2 + m_disp_params->move_y;

            m_disp_params->zoom_factor += dy*2;

            if(m_disp_params->zoom_factor < 100) {
                  m_disp_params->zoom_factor = 100;
            }
            
            if(m_disp_params->zoom_factor > 1000) {
                  m_disp_params->zoom_factor = 1000;
            }

            get_zoom_wh(wo, ho);

            m_disp_params->move_x = dxm - wo/2;
            m_disp_params->move_y = dym - ho/2;

            bitstretch();
            
            m_drag_start_y = y;
            
            update();
      }

      if(m_drag_button == 3) {
            gdouble dx = x - m_drag_start_x;
            gdouble dy = y - m_drag_start_y;

            m_disp_params->move_x -= (int)dx;
            m_disp_params->move_y -= (int)dy;

            bitstretch();

            m_drag_start_x = x;
            m_drag_start_y = y;

            update();
      }

      m_changed = true;

      signal_changed(get_id(), false);

      block = true;
      while(Gtk::Main::events_pending()) Gtk::Main::iteration(false);
      block = false;

      return true;
}

void Display::set_window_palette(gdouble x, gdouble y) {
      gdouble c,w;

      // convert x,y to center & width of windowlevel
      gdouble dx = x - m_drag_start_x;
      gdouble dy = y - m_drag_start_y;

      int dist = m_image->max_value() - m_image->min_value();
      if(dist > 5) {
            c = m_drag_window.center + (dx / get_width()) * dist/2;
            w = m_drag_window.width + (dy / get_height()) * dist/2;
      }
      else {
            c = m_drag_window.center + (dx / get_width()) * (m_windowmap_size-1)/2;
            w = m_drag_window.width + (dy / get_height()) * (m_windowmap_size-1)/2;
      }

      if(c < 1 && !m_image->is_signed()) {
            c=1;
      }
      
      if(c > m_windowmap_size-1) {
            c = m_windowmap_size-1;
      }

      if(w < 1) {
            w = 1;
      }
      
      if(w > (m_windowmap_size-1)*2) {
            w = (m_windowmap_size-1)*2;
      }

      set_windowlevels((int)c, (int)w);
      bitstretch();
}

bool Display::get_selected() {
      if(!m_disp_params) {
            return false;
      }
      
      return m_disp_params->selected;
}

void Display::set_selected(bool selected) {
      m_disp_params->selected = selected;
      queue_draw();
}

void Display::draw_ruler_v() {
      if(!m_image) {
            return;
      }

      if(m_image->spacing_y() == 0) {
            return;
      }

      int ruler_height = get_height()/2;
      
      int line_width1 = (get_width() * 20) / 1280;
      int line_width2 = line_width1*2;

      int mm = (int)((ruler_height / m_magnifier) * m_image->spacing_y());
      
      // round to 10 mm
      mm /= 10;
      mm *= 10;
      
      ruler_height = (int)((mm / m_image->spacing_y()) * m_magnifier);
      
      int offset = (get_height() - ruler_height) / 2;

      m_window->draw_line(m_GC, get_width()-m_offset_right, offset, get_width()-m_offset_right, offset+ruler_height);
      
      int ym = 0;
      for(int y=0; y<mm+1; y+=10) {
            ym = (int)((y / m_image->spacing_y()) * m_magnifier);
            int lw = line_width1;
            div_t result;
            result = div (y, 50);
            if(result.rem == 0) {
                  lw = line_width2;
            }
            m_window->draw_line(
                  m_GC,
                  get_width()-m_offset_right-lw,
                  offset+ym,
                  get_width()-m_offset_right,
                  offset+ym);
      }

      char buffer[10];
      g_snprintf(buffer, sizeof(buffer), gettext("%i mm"), mm);
      m_layoutR->set_text(buffer);
      m_layoutR->set_width(100 * PANGO_SCALE);

      m_window->draw_layout(m_GC, get_width()-100-m_offset_right, offset + ym + 3, m_layoutR);

}

void Display::draw_ruler_h() {
      if(!m_image) {
            return;
      }

      if(m_image->spacing_x() == 0) {
            return;
      }

      int ruler_width = get_width()/2;
      
      int line_height1 = (get_width() * 20) / 1280;
      int line_height2 = line_height1*2;

      int mm = (int)((ruler_width / m_magnifier) * m_image->spacing_x());
      
      // round to 10 mm
      mm /= 10;
      mm *= 10;
      
      ruler_width = (int)((mm / m_image->spacing_x()) * m_magnifier);
      
      int offset = (get_width() - ruler_width) / 2;

      m_window->draw_line(m_GC, offset, get_height()-10, offset+ruler_width, get_height()-10);
      
      int xm = 0;
      for(int x=0; x<mm+1; x+=10) {
            xm = (int)((x / m_image->spacing_x()) * m_magnifier);
            int lh = line_height1;
            div_t result;
            result = div (x, 50);
            if(result.rem == 0) {
                  lh = line_height2;
            }
            m_window->draw_line(
                  m_GC,
                  offset+xm,
                  get_height()-10-lh,
                  offset+xm,
                  get_height()-10);
      }

      char buffer[10];
      g_snprintf(buffer, sizeof(buffer), gettext("%i mm"), mm);
      m_layoutL->set_text(buffer);
      m_layoutL->set_width(100 * PANGO_SCALE);

      int tw = 0;
      int th = 0;
      m_layoutL->get_pixel_size(tw, th);

      m_window->draw_layout(m_GC, offset + xm + 3, get_height()-10-th, m_layoutL);

}

void Display::draw_line(const ImagePool::Instance::Point& p0, const ImagePool::Instance::Point& p1) {
      if(!m_image) {
            return;
      }

      int x0;
      int y0;
      int x1;
      int y1;
      ImagePool::Instance::Point s0;
      ImagePool::Instance::Point s1;

      if(!m_image->transform_to_viewport(p0, s0)) {
            return;
      }

      if(!point_to_screen(s0, x0, y0)) {
            return;
      }

      if(!m_image->transform_to_viewport(p1, s1)) {
            return;
      }

      if(!point_to_screen(s1, x1, y1)) {
            return;
      }

      if(x0 == x1 && y0 == y1) {
            return;
      }

      m_window->draw_line(m_GC, x0, y0, x1, y1);
}

void Display::draw_cross(const ImagePool::Instance::Point& p) {
      if(!m_image) {
            return;
      }

      int x;
      int y;
      ImagePool::Instance::Point p1;
      
      if(!m_image->transform_to_viewport(p, p1)) {
            return;
      }

      if(!point_to_screen(p1, x, y)) {
            return;
      }
      
      m_window->draw_line(m_GC, x-5, y, x+5, y);
      m_window->draw_line(m_GC, x, y-5, x, y+5);
}

void Display::draw_point(const ImagePool::Instance::Point& p) {
      if(!m_image) {
            return;
      }

      int x;
      int y;
      ImagePool::Instance::Point p1;
      
      if(!m_image->transform_to_viewport(p, p1)) {
            return;
      }

      if(!point_to_screen(p1, x, y)) {
            return;
      }
      
      m_window->draw_rectangle(m_GC, false, x-1, y-1, 2, 2);
}

void Display::enable_mouse_functions(bool enable) {
      std::cout << "Display::enable_mouse_functions()" << std::endl;
      m_mouse_functions = enable;
}


} // namespace Aeskulap

Generated by  Doxygen 1.6.0   Back to index