📄 ccc_x11.cpp
字号:
/*
COPYRIGHT (C) 1994 - 2002 Cay S. Horstmann. All Rights Reserved.
NOTE TO STUDENTS: Do not attempt to study the contents of this file. You
can, and should, use the services provided in this file without knowing
the highly technical details of the implementation.
*/
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "ccc_x11.h"
/* CONSTANTS ****************************************************************/
const double DEFAULT_XMIN = -10;
const double DEFAULT_YMIN = 10;
const double DEFAULT_XMAX = 10;
const double DEFAULT_YMAX = -10;
static int DEF_WIDTH = 480;
static int DEF_HEIGHT = 480;
// The following is an alias for an X fonts.
// Make sure this is available on your system. Substitute as necessary.
#define SYS_FONT_NAME "-adobe-courier-bold-r-normal-*-14-*-*-*-*-*-*"
/* Our program wrapper. */
extern int ccc_win_main();
GraphicWindow cwin;
/**************************************************************************/
GraphicWindow::GraphicWindow()
: _user_xmin(DEFAULT_XMIN), _user_ymin(DEFAULT_YMIN),
_user_xmax(DEFAULT_XMAX), _user_ymax(DEFAULT_YMAX),
_disp_xmax(DEF_WIDTH), _disp_ymax(DEF_HEIGHT)
{
}
void GraphicWindow::open(Display* d, Window w)
{
display = d;
win = w;
screen_num = DefaultScreen(display);
XGCValues xgc_values; // ignored
xgc = XCreateGC(display, win, 0, &xgc_values);
// specify black foreground since default window background is
// white and default foreground is undefined.
XSetForeground(display, xgc, BlackPixel(display, screen_num));
// set line attributes. This class only uses rounded styles.
XSetLineAttributes(display, xgc, 2 /* pen thickness */, LineSolid,
CapRound, JoinRound);
// set up the font - uses only 14pt bold Courier
_fontinfo_ptr = XLoadQueryFont(display, SYS_FONT_NAME);
if (_fontinfo_ptr == NULL)
{ cerr << "Unable to initialize font: " << SYS_FONT_NAME << endl;
exit(1);
}
XSetFont(display, xgc, _fontinfo_ptr->fid);
// sets the rop mode, using Copy for the user prompts
XSetFunction(display, xgc, GXcopy /*0x3 COPY*/);
_ppm = XCreatePixmap(display, win, DEF_WIDTH, DEF_HEIGHT,
DefaultDepth(display, screen_num));
clear();
}
void GraphicWindow::close()
{
XFreePixmap(display, _ppm);
XFreeFont(display, _fontinfo_ptr);
}
void GraphicWindow::repaint()
{
XCopyArea(display, _ppm, win, xgc, 0, 0, DEF_WIDTH, DEF_HEIGHT, 0, 0);
}
void GraphicWindow::clear()
{
XClearWindow(display, win);
XGCValues vals;
XGetGCValues(display, xgc, GCForeground, &vals);
unsigned long color = WhitePixel(display, screen_num);
unsigned long fg = vals.foreground;
XSetForeground(display, xgc, color);
XFillRectangle(display, _ppm, xgc, 0, 0, DEF_WIDTH + 1, DEF_HEIGHT + 1);
XSetForeground(display, xgc, fg);
}
void GraphicWindow::coord(double xmin, double ymin,
double xmax, double ymax)
{
_user_xmin = xmin;
_user_xmax = xmax;
_user_ymin = ymin;
_user_ymax = ymax;
}
int GraphicWindow::user_to_disp_x(double x) const
{
return (int) ((x - _user_xmin) * _disp_xmax / (_user_xmax - _user_xmin));
}
int GraphicWindow::user_to_disp_y(double y) const
{
return (int) ((y - _user_ymin) * _disp_ymax / (_user_ymax - _user_ymin));
}
int GraphicWindow::user_to_disp_dx(double x) const
{
return (int) (x * _disp_xmax / (_user_xmax - _user_xmin));
}
int GraphicWindow::user_to_disp_dy(double y) const
{
return (int) (y * _disp_ymax / (_user_ymax - _user_ymin));
}
double GraphicWindow::disp_to_user_x(int x) const
{
return (double)x * (_user_xmax - _user_xmin) / _disp_xmax + _user_xmin;
}
double GraphicWindow::disp_to_user_y(int y) const
{
return (double)y * (_user_ymax - _user_ymin) / _disp_ymax + _user_ymin;
}
void GraphicWindow::point(double x, double y)
{
const int POINT_RADIUS = 3;
int disp_x = user_to_disp_x(x);
int disp_y = user_to_disp_y(y);
XSetForeground(display, xgc, BlackPixel(display, screen_num));
XDrawArc(display, win, xgc, disp_x - POINT_RADIUS, disp_y - POINT_RADIUS,
2 * POINT_RADIUS, 2 * POINT_RADIUS, 0 , 360 * 64);
XDrawArc(display, _ppm, xgc, disp_x - POINT_RADIUS,
disp_y - POINT_RADIUS, 2 * POINT_RADIUS, 2 * POINT_RADIUS, 0 , 360 * 64);
}
void GraphicWindow::ellipse(double x, double y, double ra, double rb)
{
int disp_x = user_to_disp_x(x);
int disp_y = user_to_disp_y(y);
int disp_rx = abs(user_to_disp_dx(ra));
int disp_ry = abs(user_to_disp_dy(rb));
XSetForeground(display, xgc, BlackPixel(display, screen_num));
XDrawArc(display, win,
xgc, // the drawable
disp_x - disp_rx, // the x coord of upperleft corner of bounding rect
disp_y - disp_ry, // the y coord of upperleft corner of bounding rect
disp_rx * 2, // the major axis length
disp_ry * 2, // the minor axis length
0, // offset from 3 o'clock
360 * 64); // complete circle (360 degrees * 64 clicks per degree)
XDrawArc(display, _ppm, xgc, disp_x - disp_rx,
disp_y - disp_ry, disp_rx * 2, disp_ry * 2, 0, 360 * 64);
}
void GraphicWindow::line(double xfrom, double yfrom, double xto,
double yto)
{
XSetForeground(display, xgc, BlackPixel(display, screen_num));
XDrawLine(display, win, xgc, user_to_disp_x(xfrom), user_to_disp_y(yfrom),
user_to_disp_x(xto), user_to_disp_y(yto));
XDrawLine(display, _ppm, xgc, user_to_disp_x(xfrom),
user_to_disp_y(yfrom), user_to_disp_x(xto), user_to_disp_y(yto));
}
void GraphicWindow::text(const char t[], double x, double y)
{
int direction, ascent, descent;
XCharStruct overall;
XTextExtents(_fontinfo_ptr, t, strlen(t), &direction, &ascent, &descent, &overall);
int disp_x = user_to_disp_x(x);
int disp_y = user_to_disp_y(y) + ascent;
XSetForeground(display, xgc, BlackPixel(display, screen_num));
XDrawString(display, win, xgc, disp_x, disp_y, t, strlen(t));
XDrawString(display, _ppm, xgc, disp_x, disp_y,
t, strlen(t));
}
GraphicWindow& GraphicWindow::operator<<(Point p)
{
point(p.get_x(), p.get_y());
return *this;
}
GraphicWindow& GraphicWindow::operator<<(Circle c)
{
ellipse (c.get_center().get_x(),
c.get_center().get_y(),
c.get_radius(),
c.get_radius());
return *this;
}
GraphicWindow& GraphicWindow::operator<<(Message m)
{
_display_string = m.get_text();
text(_display_string.c_str(), m.get_start().get_x(), m.get_start().get_y());
return *this;
}
GraphicWindow& GraphicWindow::operator<< (Line l)
{
line(l.get_start().get_x(), l.get_start().get_y(),
l.get_end().get_x(), l.get_end().get_y());
return *this;
}
void GraphicWindow::statusline_prompt(string s)
{
int direction, ascent, descent;
XCharStruct overall;
const char* t = s.c_str();
XTextExtents(_fontinfo_ptr, t, strlen(t),
&direction, &ascent, &descent, &overall);
XSetBackground(display, xgc, WhitePixel(display, screen_num));
XClearArea(display, win,
0,
0, /*clear from top*/
0 /*clear to right edge of screen*/,
ascent + descent,
0 /* generate exposure events */);
XDrawImageString(display, win, xgc, 0, ascent, t, strlen(t));
XDrawImageString(display, _ppm, xgc, 0, ascent, t, strlen(t));
}
Point GraphicWindow::get_mouse(string outstr)
{
XEvent report;
Point p;
int x, y;
cwin.statusline_prompt(outstr);
// Event Loop
while (true)
{
XNextEvent(display, &report);
switch(report.type)
{
case Expose:
cwin.repaint();
break;
case ButtonPress:
if (report.xbutton.button == Button1)
{
x = report.xbutton.x;
y = report.xbutton.y;
p = Point(cwin.disp_to_user_x(x), cwin.disp_to_user_y(y));
cwin.statusline_prompt(outstr);
return p;
}
}
}
return p; // to keep compiler happy, will never get here!
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -