Use room list

This commit is contained in:
Matthias Schiffer 2010-01-09 03:18:25 +01:00
parent 2bd663e0db
commit b4adc20ef0
11 changed files with 272 additions and 49 deletions

View file

@ -14,7 +14,7 @@ ENDIF (NOT OPENGL_FOUND)
find_package(PkgConfig)
pkg_check_modules(XMLPP REQUIRED libxml++-2.6>=2.24)
pkg_check_modules(GTKMM REQUIRED glibmm-2.4>=2.16 gtkmm-2.4>=2.16)
pkg_check_modules(GTKMM REQUIRED glibmm-2.4>=2.16 gtkmm-2.4>=2.18)
pkg_check_modules(GTKGLEXT REQUIRED gtkglext-1.0)
#include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${XMLPP_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GTKGLEXT_INCLUDE_DIRS})

View file

@ -10,6 +10,7 @@ add_executable(zoomedit
Gui/AspectFrame.h
Gui/RenderArea.cpp Gui/RenderArea.h
Gui/Window.cpp Gui/Window.h
Gui/Renderer/RoomListRenderer.cpp Gui/Renderer/RoomListRenderer.h
Math/Triangle2D.cpp Math/Triangle2D.h

View file

@ -0,0 +1,66 @@
/*
* RoomListRenderer.cpp
*
* Copyright (C) 2010 Matthias Schiffer <matthias@gamezock.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "RoomListRenderer.h"
#include <Data/Room.h>
#include <pangomm/layout.h>
namespace ZoomEdit {
namespace Gui {
namespace Renderer {
void RoomListRenderer::get_size_vfunc(Gtk::Widget &/*widget*/, const Gdk::Rectangle * /*cell_area*/,
int * /*x_offset*/, int * /*y_offset*/, int * /*width*/, int *height) const {
int xpad, ypad;
get_padding(xpad, ypad);
*height = 60 + ypad*2;
}
void RoomListRenderer::render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window, Gtk::Widget &widget,
const Gdk::Rectangle &/*background_area*/, const Gdk::Rectangle &cell_area,
const Gdk::Rectangle &/*expose_area*/, Gtk::CellRendererState /*flags*/) {
Data::Room *room = reinterpret_cast<Data::Room*>(value.get_value());
int xpad, ypad;
get_padding(xpad, ypad);
int x = xpad + cell_area.get_x();
int y = ypad + cell_area.get_y();
int width = cell_area.get_width() - 2*xpad;
int height = cell_area.get_height() - 2*ypad;
Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create(window);
gc->set_rgb_fg_color(Gdk::Color("000000"));
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(widget.get_pango_context());
layout->set_width(width);
layout->set_height(height);
layout->set_markup("<b>" + room->getId() + "</b>");
window->draw_layout(gc, x, y, layout);
}
}
}
}

View file

@ -0,0 +1,53 @@
/*
* RoomListRenderer.h
*
* Copyright (C) 2010 Matthias Schiffer <matthias@gamezock.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ZOOMEDIT_GUI_RENDERER_ROOMLISTRENDERER_H_
#define ZOOMEDIT_GUI_RENDERER_ROOMLISTRENDERER_H_
#include <gtkmm/cellrenderer.h>
namespace ZoomEdit {
namespace Gui {
namespace Renderer {
class RoomListRenderer : public virtual Glib::ObjectBase, public Gtk::CellRenderer {
public:
RoomListRenderer() : Glib::ObjectBase(typeid(RoomListRenderer)), value(*this, "value") {}
Glib::PropertyProxy<void*> property_value() {
return value.get_proxy();
}
protected:
virtual void get_size_vfunc(Gtk::Widget &widget, const Gdk::Rectangle *cell_area,
int *x_offset, int *y_offset, int *width, int *height) const;
virtual void render_vfunc(const Glib::RefPtr<Gdk::Drawable> &window, Gtk::Widget &widget,
const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area,
const Gdk::Rectangle &expose_area, Gtk::CellRendererState flags);
private:
Glib::Property<void*> value;
};
}
}
}
#endif /* ZOOMEDIT_GUI_RENDERER_ROOMLISTRENDERER_H_ */

View file

@ -26,6 +26,8 @@
namespace ZoomEdit {
namespace Gui {
const Window::RoomListColumnRecord Window::ROOM_LIST_COLUMN_RECORD;
Window::Window(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &builder)
: Gtk::Window(cobject) {
@ -37,6 +39,18 @@ Window::Window(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &builde
builder->get_widget_derived("RenderArea", renderArea);
builder->get_widget_derived("MapArea", mapArea);
builder->get_widget_derived("AspectFrameMap", aspectFrameMap);
roomListStore = Gtk::ListStore::create(ROOM_LIST_COLUMN_RECORD);
builder->get_widget("RoomList", roomList);
roomList->set_model(roomListStore);
int colCount = roomList->append_column("Room", roomListRenderer);
Gtk::TreeViewColumn *roomColumn = roomList->get_column(colCount-1);
if(roomColumn) {
roomColumn->add_attribute(roomListRenderer.property_value(), ROOM_LIST_COLUMN_RECORD.room);
}
}
Window::~Window() {

View file

@ -21,25 +21,55 @@
#define ZOOMEDIT_GUI_WINDOW_H_
#include <gtkmm/builder.h>
#include <gtkmm/liststore.h>
#include <gtkmm/treeview.h>
#include <gtkmm/window.h>
#include "Renderer/RoomListRenderer.h"
namespace ZoomEdit {
namespace Data {
class Room;
}
namespace Gui {
class AspectFrame;
class RenderArea;
class Window : public Gtk::Window {
private:
RenderArea *renderArea, *mapArea;
AspectFrame *aspectFrameMap;
public:
Window(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &builder);
virtual ~Window();
RenderArea* getRenderArea() const {return renderArea;}
RenderArea* getMapArea() const {return mapArea;}
Glib::RefPtr<Gtk::ListStore> getRoomListStore() {return roomListStore;}
Gtk::TreeView* getRoomList() {return roomList;}
class RoomListColumnRecord : public Gtk::TreeModel::ColumnRecord {
public:
friend class Window;
Gtk::TreeModelColumn<void*> room;
private:
RoomListColumnRecord() {
add(room);
}
};
static const RoomListColumnRecord ROOM_LIST_COLUMN_RECORD;
private:
RenderArea *renderArea, *mapArea;
AspectFrame *aspectFrameMap;
Gtk::TreeView *roomList;
Glib::RefPtr<Gtk::ListStore> roomListStore;
Renderer::RoomListRenderer roomListRenderer;
};
}

View file

@ -18,21 +18,24 @@
*/
#include "Instance.h"
#include <Gui/Window.h>
#include <Gui/RenderArea.h>
#include <Data/Level.h>
#include <Data/Room.h>
#include <View/TopView.h>
#include <View/MapView.h>
#include <iostream>
#include <libxml++/validators/dtdvalidator.h>
#include <libxml/tree.h>
#include <gtkmm/toolbutton.h>
#include <Gui/Window.h>
#include <Gui/RenderArea.h>
#include <Data/Level.h>
#include <View/TopView.h>
#include <View/MapView.h>
namespace ZoomEdit {
guint Instance::instances = 0;
Instance::Instance(const Glib::ustring &file) : window(0), levelXml(0), level(0), view(0) {
Instance::Instance(const Glib::ustring &file) : window(0), view(0), levelXml(0), level(0), selectedRoom(0) {
instances++;
try {
@ -50,13 +53,16 @@ Instance::Instance(const Glib::ustring &file) : window(0), levelXml(0), level(0)
}
window->signal_hide().connect(sigc::mem_fun(this, &Instance::destroy));
window->getRoomList()->get_selection()->signal_changed().connect(sigc::mem_fun(this, &Instance::onRoomListSelect));
view = new View::TopView();
view = new View::TopView(this);
window->getRenderArea()->setView(view);
mapView = new View::MapView(view);
window->getMapArea()->setView(mapView);
view->signalUpdate().connect(sigc::mem_fun(this, &Instance::onUpdate));
Gtk::ToolButton *button;
builder->get_widget("ToolButtonZoomIn", button);
button->signal_clicked().connect(sigc::bind(sigc::mem_fun(view, &View::TopView::zoom), 2, 0, 0));
@ -93,14 +99,54 @@ Instance::~Instance() {
Gtk::Main::quit();
}
void Instance::createLevel() {
void Instance::setSelectedRoom(Data::Room *newSelectedRoom) {
if(selectedRoom == newSelectedRoom)
return;
selectedRoom = newSelectedRoom;
view->signalUpdate().emit();
}
void Instance::onUpdate() {
window->getRoomListStore()->clear();
const std::list<Data::Room*> rooms = level->getRooms();
for(std::list<Data::Room*>::const_iterator room = rooms.begin(); room != rooms.end(); ++room) {
Gtk::ListStore::iterator row = window->getRoomListStore()->append();
row->set_value(Gui::Window::ROOM_LIST_COLUMN_RECORD.room, static_cast<void*>(*room));
if(*room == selectedRoom) {
window->getRoomList()->get_selection()->select(row);
}
}
}
void Instance::onRoomListSelect() {
Gtk::ListStore::iterator row = window->getRoomList()->get_selection()->get_selected();
if(!window->getRoomListStore()->iter_is_valid(row))
return;
setSelectedRoom(static_cast<Data::Room*>(row->get_value(Gui::Window::ROOM_LIST_COLUMN_RECORD.room)));
}
void Instance::deleteLevel() {
if(level) {
view->setLevel(0);
delete level;
level = 0;
view->signalUpdate().emit();
}
if(levelXml)
delete levelXml;
}
void Instance::setLevel() {
view->signalUpdate().emit();
}
void Instance::createLevel() {
deleteLevel();
levelXml = new xmlpp::DomParser;
xmlpp::Document *doc = levelXml->get_document();
@ -125,18 +171,11 @@ void Instance::createLevel() {
level = new Data::Level(root);
view->setLevel(level);
setLevel();
}
bool Instance::loadLevel(const Glib::ustring &file) {
if(level) {
view->setLevel(0);
delete level;
level = 0;
}
if(levelXml)
delete levelXml;
deleteLevel();
levelXml = new xmlpp::DomParser(file);
xmlpp::Document *doc = levelXml->get_document();
@ -149,7 +188,7 @@ bool Instance::loadLevel(const Glib::ustring &file) {
level = new Data::Level(doc->get_root_node());
view->setLevel(level);
setLevel();
return true;
}

View file

@ -21,7 +21,9 @@
#define ZOOMEDIT_INSTANCE_H_
#include <gtkmm/builder.h>
#include <gtkmm/treeview.h>
#include <gtkmm/main.h>
#include <libxml++/parsers/domparser.h>
namespace ZoomEdit {
@ -32,6 +34,7 @@ class Window;
namespace Data {
class Level;
class Room;
}
namespace View {
@ -47,6 +50,11 @@ class Instance {
bool loadLevel(const Glib::ustring &file);
bool saveLevel(const Glib::ustring &file);
Data::Level* getLevel() {return level;}
Data::Room* getSelectedRoom() {return selectedRoom;}
void setSelectedRoom(Data::Room *newSelectedRoom);
static bool create(const Glib::ustring &file = Glib::ustring());
private:
@ -55,16 +63,24 @@ class Instance {
Glib::RefPtr<Gtk::Builder> builder;
Gui::Window *window;
xmlpp::DomParser *levelXml;
Data::Level *level;
View::TopView *view;
View::MapView *mapView;
xmlpp::DomParser *levelXml;
Data::Level *level;
Data::Room *selectedRoom;
Instance(const Glib::ustring &file);
void destroy();
void onUpdate();
void onRoomListSelect();
void deleteLevel();
void setLevel();
// Prevent shallow copy
Instance(const Instance &o);
Instance& operator=(const Instance &o);

View file

@ -19,10 +19,13 @@
#include "MapView.h"
#include "TopView.h"
#include <Instance.h>
#include <Data/Level.h>
#include <Data/Room.h>
#include <Data/Triangle.h>
#include <Gui/RenderArea.h>
#include <GL/gl.h>
#include <cmath>
#include <list>
@ -96,7 +99,7 @@ void MapView::click(float x, float y, unsigned int button) {
void MapView::render() {
glClear(GL_COLOR_BUFFER_BIT);
if(!mainView || !mainView->getLevel())
if(!mainView || !mainView->getInstance()->getLevel())
return;
float minX, maxX, minY, maxY;
@ -116,10 +119,10 @@ void MapView::render() {
glScalef(scale, scale, 1);
glTranslatef(-xCenter, -yCenter, 0);
const std::list<Data::Room*> &rooms = mainView->getLevel()->getRooms();
const std::list<Data::Room*> &rooms = mainView->getInstance()->getLevel()->getRooms();
for(std::list<Data::Room*>::const_iterator room = rooms.begin(); room != rooms.end(); ++room)
TopView::renderRoom(*room);
TopView::renderRoom(*room, (*room == mainView->getInstance()->getSelectedRoom()));
float mainXCenter = mainView->getXCenter(), mainYCenter = mainView->getYCenter();
float mainScale = mainView->getScale();
@ -163,10 +166,10 @@ void MapView::getBounds(float *minX, float *maxX, float *minY, float *maxY) {
if(maxY)
*maxY = 0;
if(!mainView || !mainView->getLevel())
if(!mainView || !mainView->getInstance()->getLevel())
return;
const std::list<Data::Room*> &rooms = mainView->getLevel()->getRooms();
const std::list<Data::Room*> &rooms = mainView->getInstance()->getLevel()->getRooms();
for(std::list<Data::Room*>::const_iterator room = rooms.begin(); room != rooms.end(); ++room) {
const std::list<Data::Triangle*> &triangles = (*room)->getTriangles();

View file

@ -18,11 +18,14 @@
*/
#include "TopView.h"
#include <Instance.h>
#include <Data/Level.h>
#include <Data/Room.h>
#include <Data/Triangle.h>
#include <Gui/RenderArea.h>
#include <Math/Triangle2D.h>
#include <GL/gl.h>
#include <cmath>
#include <set>
@ -218,13 +221,13 @@ void TopView::render() {
drawGrid();
if(!level)
if(!instance->getLevel())
return;
const std::list<Data::Room*> &rooms = level->getRooms();
const std::list<Data::Room*> &rooms = instance->getLevel()->getRooms();
for(std::list<Data::Room*>::const_iterator room = rooms.begin(); room != rooms.end(); ++room)
renderRoom(*room, *room == selectedRoom);
renderRoom(*room, *room == instance->getSelectedRoom());
}
void TopView::click(float x, float y, unsigned int button) {
@ -233,9 +236,9 @@ void TopView::click(float x, float y, unsigned int button) {
vmml::vec2f v(xCenter + x/scale, yCenter + y/scale);
selectedRoom = 0;
Data::Room *selectedRoom = 0;
const std::list<Data::Room*>& rooms = level->getRooms();
const std::list<Data::Room*> &rooms = instance->getLevel()->getRooms();
for(std::list<Data::Room*>::const_iterator room = rooms.begin(); room != rooms.end(); ++room) {
const std::list<Data::Triangle*>& triangles = (*room)->getTriangles();
@ -255,6 +258,7 @@ void TopView::click(float x, float y, unsigned int button) {
break;
}
instance->setSelectedRoom(selectedRoom);
signalUpdate().emit();
}

View file

@ -27,6 +27,8 @@
namespace ZoomEdit {
class Instance;
namespace Data {
class Level;
class Room;
@ -45,7 +47,7 @@ class TopView : public View {
bool operator<(const Edge &e) const;
};
Data::Level *level;
Instance *instance;
float viewWidth, viewHeight;
@ -54,13 +56,13 @@ class TopView : public View {
int zoomLevel;
float scale;
Data::Room *selectedRoom;
void drawGrid();
public:
TopView(Data::Level *level0 = 0)
: level(level0), viewWidth(0), viewHeight(0), xCenter(0), yCenter(0), zoomLevel(0), scale(100), selectedRoom(0) {}
TopView(Instance *instance0)
: instance(instance0), viewWidth(0), viewHeight(0), xCenter(0), yCenter(0), zoomLevel(0), scale(100) {}
Instance* getInstance() {return instance;}
float getWidth() const {return viewWidth;}
float getHeight() const {return viewHeight;}
@ -72,11 +74,6 @@ class TopView : public View {
float getScale() const {return scale;}
Data::Room* getSelectedRoom() {return selectedRoom;}
Data::Level* getLevel() {return level;}
void setLevel(Data::Level *level0) {level = level0; signalUpdate().emit();}
virtual void init();
virtual void resize(float width, float height);