#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MAXF 400 // maks. ilość przechowywanych w tablicy figur
#define MAXK 5 // ilość kolorów w tablicy
#define PWIDTH 100 // długość prostokąta
#define PHEIGHT 60 // wysokość prostokąta
#define KWIDTH 80 // średnica koła
typedef struct { // struktura figura; x,y-współrzędne środka figury, typ - 1 oznacza prostokąt, 2 koło, kolor - numer koloru z tablicy
int x, y, typ, kolor;
} figura;
int main(int argc, char *argv[])
{
char icon_name[] = "Grafika";
char title[] = "Grafika komputerowa";
Display* display; //gdzie bedziemy wysylac dane (do jakiego X servera)
Window window; //nasze okno, gdzie bedziemy dokonywac roznych operacji
GC gc; //tu znajduja sie informacje o parametrach graficznych
XEvent event; //gdzie bedziemy zapisywac pojawiajace sie zdarzenia
KeySym key; //informacja o stanie klawiatury
XSizeHints info; //informacje typu rozmiar i polozenie okna
int screen_no;
unsigned long foreground;
unsigned long background;
char buffer[8]; //gdzie bedziemy zapamietywac znaki z klawiatury
int hm_keys; //licznik klawiszy
int to_end;
XPoint current_point;
Colormap colormap;
int red, green, blue, yellow;
figura figbuf[MAXF]; // tablica z figurami
int fi=0,fim=0,i=0,idf=-1; // zmienne pomocnicze
int kolor[MAXK]; // tablica kolorów
double odleglosc=0; // zmienna pomocnicza do obliczania odległości
display = XOpenDisplay(""); //otworz polaczenie z X serverem pobierz dane od zmiennej srodowiskowej DISPLAY ("")
screen_no = DefaultScreen(display); //pobierz domyslny ekran dla tego wyswietlacza (0)
background = WhitePixel(display, screen_no); //niech tlo bedzie biale
foreground = BlackPixel(display, screen_no); //niech ekran bedzie czarny
colormap = DefaultColormap(display,screen_no);
int AllocNamedColor(char *name) //funkcja przydzielania kolorow
{
XColor col;
XParseColor(display,colormap,name,&col);
XAllocColor(display,colormap,&col);
return col.pixel;
}
red=AllocNamedColor("red");
green=AllocNamedColor("green");
blue=AllocNamedColor("blue");
yellow=AllocNamedColor("yellow");
// kolory w tablicy
kolor[0]=AllocNamedColor("black");
kolor[1]=red;
kolor[2]=green;
kolor[3]=blue;
kolor[4]=yellow;
//okresl rozmiar i polozenie okna
info.x = 100;
info.y = 150;
info.width = 600;
info.height = 300;
info.flags = PPosition | PSize;
//majac wyswietlacz, stworz okno - domyslny uchwyt okna
window = XCreateSimpleWindow(display, DefaultRootWindow(display),
info.x, info.y, info.width, info.height,
7/* grubosc ramki */, foreground, background);
XSetStandardProperties(display, window, title, icon_name, None,
argv, argc, &info);
//utworz kontekst graficzny do zarzadzania parametrami graficznymi (0,0) domyslne wartosci
gc = XCreateGC(display, window, 0, 0);
XSetBackground(display, gc, background);
XSetForeground(display, gc, foreground);
/* okresl zdarzenia jakie nas interesuja tj. nacisniecie
klawisza (aby wyjsc z programu, oraz zdarzenie
odswiezania okna np. gdy jakies inne window, ktore
przykrywalo nasze okno zostalo zamkniete lub przesuniete,
nacisniecie klawisza, zwolnienie oraz ruch myszy*/
XSelectInput(display, window, (KeyPressMask | ExposureMask | ButtonPressMask|
ButtonReleaseMask | Button1MotionMask));
XMapRaised(display, window); //wyswietl nasze okno na samym wierzchu wszystkich okien
to_end = FALSE;
/* petla najpierw sprawdza, czy warunek jest spelniony
i jesli tak, to nastepuje przetwarzanie petli
a jesli nie, to wyjscie z petli, bez jej przetwarzania */
while (to_end == FALSE)
{
XNextEvent(display, &event); // czekaj na zdarzenia okreslone wczesniej przez funkcje XSelectInput
switch(event.type)
{
case Expose:
if (event.xexpose.count == 0)
{
//tu powinna byc przerysowana zawartosc okna
for (i=0;i<=fim;i++) { // przechodzimy przez tablicę figur
XSetForeground(display, gc, kolor[figbuf[i].kolor]); // ustawiamy kolor jakim mamy narysować figurę
if (figbuf[i].typ==1) {
XFillRectangle(display,window,gc,figbuf[i].x-(PWIDTH/2),figbuf[i].y-(PHEIGHT/2),PWIDTH,PHEIGHT); // rysujemy prostokąt
} else if (figbuf[i].typ==2) {
XFillArc(display,window,gc,figbuf[i].x-(KWIDTH/2),figbuf[i].y-(KWIDTH/2),KWIDTH,KWIDTH,0,360*64); // rysujemy koło
}
}
}
break;
case MappingNotify:
XRefreshKeyboardMapping(&event.xmapping); // zmiana ukladu klawiatury - w celu zabezpieczenia sie przed taka zmiana trzeba to wykonac
break;
case ButtonPress:
if (event.xbutton.button == Button1 || event.xbutton.button == Button3) // sprawdzenie czy wciscnieto lewy lub prawy przycisk
{
//odczytanie polozenia kursora
current_point.x = event.xbutton.x;
current_point.y = event.xbutton.y;
for (i=0;i<=fim;i++) { // przechodzimy w pętli przez tablicę figur w celu sprawdzenia czy kliknięto na figurze
odleglosc = ((current_point.x-figbuf[i].x)*(current_point.x-figbuf[i].x))+((current_point.y-figbuf[i].y)*(current_point.y-figbuf[i].y));//obliczamy odległość punktu kliknięcia od środka figury
if (current_point.x >= figbuf[i].x-(PWIDTH/2) && current_point.x <= figbuf[i].x+(PWIDTH/2) && current_point.y >= figbuf[i].y-(PHEIGHT/2) && current_point.y <= figbuf[i].y+(PHEIGHT/2) && figbuf[i].typ==1) idf=i;
else if (odleglosc<=(KWIDTH/2)*(KWIDTH/2) && figbuf[i].typ==2) idf=i; // przypisanie do idf id figury z tablicy jeśli kliknięto na nią
}
if (idf>=0) { // jeśli kliknięto figurę zmieniamy kolor
figbuf[idf].kolor++;
if (figbuf[idf].kolor>=MAXK) figbuf[idf].kolor=0; // jeśli nie ma już koloru w tablicy przypisujemy pierwszy kolor
} else { // jesli nie robimy nową
if (fi>=MAXF) fi=0; // jesli id wychodzi poza zakres nadpisujemy 1 figurę
if (fim>MAXF) fim=MAXF; // ilość elementów w tablicy
figbuf[fi].x=current_point.x; // x srodka
figbuf[fi].y=current_point.y; // y srodka
figbuf[fi].typ=(event.xbutton.button==Button1?1:2); // jesli kliknieto lewy typ 1 (prostokat) figury jesli nie typ 2 (kolo)
figbuf[fi].kolor=0; // kolor czarny
fim++;fi++;
}
idf=-1; // czyszczenie idf
// wymuszenie odswiezenia okna
event.type = Expose;
event.xexpose.count = 0;
XSendEvent(display, window, 0, ExposureMask, &event);
}
break;
case KeyPress:
hm_keys = XLookupString(&event.xkey, buffer, 8, &key, 0);
if (hm_keys == 1)
{
if (buffer[0] == 'q') to_end = TRUE; // koniec programu
}
default:
break;
}
}
XFreeGC(display, gc);
XDestroyWindow(display, window);
XCloseDisplay(display);
return 0;
}