⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 widgets.c

📁 一个很好的SDL建立应用程序界面的例子
💻 C
📖 第 1 页 / 共 5 页
字号:
	y = ev->button.y;	where = whereInSlider(sp, x, y);	if (sp->type == VSliderType)	{		pos = y - sp->y;		len = sp->h;	}	else if (sp->type == HSliderType)	{		pos = x - sp->x;		len = sp->w;	}	else		return;	len -= (size + 2 * SLIDERBUTTONSIZE);	if (ev->type == SDL_MOUSEMOTION)	{		if (sp->drag)		{			pos -= (SLIDERBUTTONSIZE + SLIDERBUTTONSIZE / 2);			if (pos < 0)				pos = 0;			if (pos > len)				pos = len;			sp->position = pos;			pc = (pos * 100) / len;			sp->pc = pc;			sp->offset = (sp->range * pc) / 100;		}	}	else if (ev->type == SDL_MOUSEBUTTONDOWN)	{		sp->state = where;		switch (where)		{			case MOUSE_IN_UPPER_SLIDER:				adjustSlider(slider, -sp->change);				if (tweakSlider(sp, x, y, MOUSE_IN_UPPER_SLIDER))				{					sp->state = MOUSE_NOT_IN_SLIDER;					timerData.vs = NULL;					sp->drag = TRUE;				}				else				{					widgetRepeatDelay = WIDGET_SLIDER_REPEAT_DELAY;					timerData.vs = sp;				}				break;			case MOUSE_IN_LOWER_SLIDER:				adjustSlider(slider, sp->change);				if (tweakSlider(sp, x, y, MOUSE_IN_LOWER_SLIDER))				{					sp->state = MOUSE_NOT_IN_SLIDER;					timerData.vs = NULL;					sp->drag = TRUE;				}				else				{					widgetRepeatDelay = WIDGET_SLIDER_REPEAT_DELAY;					timerData.vs = sp;				}				break;			case MOUSE_ON_SLIDER:				sp->drag = TRUE;				break;			case MOUSE_IN_SLIDER_UPBUTTON:				adjustSlider(slider, -1);				widgetRepeatDelay = WIDGET_SLIDER_REPEAT_DELAY;				timerData.vs = sp;				break;			case MOUSE_IN_SLIDER_DOWNBUTTON:				adjustSlider(slider, 1);				widgetRepeatDelay = WIDGET_SLIDER_REPEAT_DELAY;				timerData.vs = sp;				break;		}	}	else if (ev->type == SDL_MOUSEBUTTONUP)	{		sp->drag = FALSE;	}}// Pop a Widget to the top of the widget listvoid popUpWidget(void *x){	if (!x || x == topWidget)		return;	removeWList(x);	addWList(x);	topWidget = x;	if (((WIDGET *) x)->p.type == InputBoxType)		timerData.vs = x;}// Remove a Widget from the widget list and update screenvoid pushDownWidget(void *x){	if (!x)		return;	removeWList(x);	updateScreen();}// Add a Widget to the widget listvoid addWList(void *w){	WLIST	*next, *prev;	if (!wlist)	{		wlist = (WLIST *) malloc(sizeof(WLIST));		next = wlist;	}	else	{		prev = NULL;		next = prev = wlist;		while (next)		{			if (next->w == w)				// already in list				return;			prev = next;			next = next->next;		}		prev->next = (WLIST *) malloc(sizeof(WLIST));		next = prev->next;	}	next->w = w;	next->next = NULL;}// Remove a Widget from the widget listvoid removeWList(void *w){	WLIST		*prev, *next;	WIDGET	*x, *y;	BLIST		*list;	if (!wlist)		return;	prev = NULL;	next = wlist;	while (next && next->w != w)			// find widget in list	{		prev = next;		next = next->next;	}	if (next)									// widget found in list	{												// remove widget from list		if (prev)								// if not first on list...			prev->next = next->next;		// unlink from list		else										// else was first on list			wlist = next->next;				// so new head is our next		x = (WIDGET *) w;		switch (x->p.type)					// check for children of this widget		{			case WindowType:			case MenuType:			case VMenuType:			case AlertType:			case NoticeType:			case TextBoxType:			case InputBoxType:				list = ((WINDOW *) x)->list;				while (list)					// remove any children found				{					y = (WIDGET *) list->thislist.button;					removeWList(y);					list = list->next;				}				break;		}		free(next);	}	next = wlist;	if (next)	{		while (next->next)			next = next->next;		topWidget = next->w;		if (((WIDGET *) topWidget)->p.type == InputBoxType)			timerData.vs = topWidget;	}	else	{		topWidget = NULL;		timerData.vs = NULL;	}}// Scan the active widget list and re-display the widgetsvoid updateScreen(void){	WLIST	*next;	blankScreen();	next = wlist;	while (next)	{		showWidget(next->w);		next = next->next;	}	SDL_UpdateRect(screen, 0, 0, 0, 0);}// Update input box stringvoid updateIBox(SDL_Event *event, INPUTBOX *b){	int		i, len, row, column;	char		*str;	Uint16	chr;	SLIST		*sl, *slprev;	if (b != topWidget)		popUpWidget(b);	if (event->type == SDL_KEYDOWN)	{		chr = event->key.keysym.unicode;		sl = b->text;		i = b->line + b->cursory;		while (i && sl)		{			sl = sl->next;			--i;		}		if (sl)		{			str = sl->str;			if (str)			{				len = strlen(str);				if (isprint(chr) && (len < b->w / FONT_WIDTH - 1 || b->mode == IBOX_OVERWRITE_MODE))				{					if (b->mode == IBOX_INSERT_MODE)						shiftStringUp(str, b->cursorx);					str[b->cursorx] = chr;					i = b->w / FONT_WIDTH - 1;					len = b->cursorx + 1;					if (len >= i)						len = i - 1;					b->cursorx = len;				}				else if (chr == '\n' || chr == '\r')				{					b->cursorx = 0;					if (b->cursory < b->vlines - 1)						b->cursory++;					else if (b->line < b->lines - b->vlines)						b->line++;				}				else if (chr == '\b' && b->cursorx)				{					b->cursorx--;					shiftStringDown(str, b->cursorx);				}				else				{					switch (event->key.keysym.sym)					{						case SDLK_DELETE:							shiftStringDown(str, b->cursorx);							break;						case SDLK_BACKSPACE:							if (b->cursorx)							{								shiftStringDown(str, b->cursorx-1);								b->cursorx -= 1;							}							break;						case SDLK_INSERT:							b->mode ^= 1;							break;						case SDLK_HOME:							b->cursorx = 0;							break;						case SDLK_END:							i = b->w / FONT_WIDTH - 1;							if (len >= i)								len = i - 1;							b->cursorx = len;							break;						case SDLK_UP:							if (b->cursory)								b->cursory--;							else if (b->line)								b->line--;							sl = b->text;							i = b->cursory + b->line;							if (i >= b->lines)								i = b->lines - 1;							while (i)							{								sl = sl->next;								--i;							}							str = sl->str;							if (str && strlen(str) < b->cursorx)								b->cursorx = strlen(str);							break;						case SDLK_DOWN:							if (b->cursory < b->vlines - 1)								b->cursory++;							else if (b->line < b->lines - b->vlines)								b->line++;							sl = b->text;							i = b->cursory + b->line;							if (i >= b->lines)								i = b->lines - 1;							while (i)							{								sl = sl->next;								--i;							}							str = sl->str;							len = strlen(str);							if (str && len < b->cursorx)								b->cursorx = len;							break;						case SDLK_LEFT:							if (b->cursorx)								b->cursorx--;							break;						case SDLK_RIGHT:							b->cursorx++;							sl = b->text;							i = b->cursory + b->line;							while (i)							{								sl = sl->next;								--i;							}							str = sl->str;							len = strlen(str) - 1;							if (len < 0)								len = 0;							if (str && len < b->cursorx)								b->cursorx = len;							break;						default:							break;					}				}			}		}	}	else if (event->type == SDL_MOUSEBUTTONDOWN)	{		if (event->button.button == SDL_BUTTON_RIGHT)		{			b->mode ^= 1;		}		else if (event->button.button == SDL_BUTTON_LEFT) // Thanks to Pat Cevasco for this mod		{			sl = b->text;// The location of the mouse click (in line and character units)			row = (event->button.y - b->y - 4) / FONT_HEIGHT;			column = (event->button.x - b->x - 4) / FONT_WIDTH;			if (column < 0)				column = 0;			i = b->line + row;			while (i)				// Find the string of the line that was clicked on			{				slprev = sl;				sl = sl->next;				if (!sl)				{					sl = slprev;					--row;					break;				}				--i;			}			str = sl->str;			len = strlen(str) - 1;		// Check the length of the line of interest			if (len < 0)				len = 0;			if (row > b->vlines - 1)				row = b->vlines - 1;			else if (row < 0)				row = 0;// Account for clicking on a location after last character of text in the line.// Use len + 1 so that the cursor will be placed after the last character.			if (len < 1)				column = 0;			else if (len + 1 < column)				column = len + 1;			b->cursorx = column;				// move cursor			b->cursory = row;		}	}}// Check widget list for callback to processvoid processCB(SDL_Event *ev){	int		x, y;	int		xlo, xhi, ylo, yhi;	WLIST		*next;	MENU		*m;	MENU		*last;	VSLIDER	*vs;	void		(*fptr)(SDL_Event *, void *);	WIDGET	*widget;	int		type;	int		evtype;	ALERT		*alert;	BLIST		*blist;	BUTTON	*btn;	void		*parent;	x = ev->button.x;	y = ev->button.y;	fptr = NULL;	widget = (WIDGET *) topWidget;	evtype = ev->type;	if (evtype == TIMER_EVENT)	{		widgetTimerCB();		return;	}	if (widget)	{		type = widget->p.type;// If any alert or notice is active (topWidget), process only mouse button// down events on the callbacks for its Cancel and Ok buttons.		if ((type == AlertType) || (type == NoticeType))		{			alert = (ALERT *) widget;			if (evtype == SDL_MOUSEBUTTONDOWN)			{				blist = alert->list;				blist = blist->next;				btn = blist->thislist.button;		// check if cancel/close button				xlo = btn->x;				xhi = xlo + btn->w;				ylo = btn->y;				yhi = ylo + btn->h;				if (x >= xlo && x <= xhi && y >= ylo && y <= yhi)				{					fptr = btn->mdfunc;					(*fptr)(ev, btn);					updateScreen();					return;				}				if (type == AlertType)				{					blist = blist->next;					btn = blist->thislist.button;		// check if ok button					xlo = btn->x;					xhi = xlo + btn->w;					ylo = btn->y;					yhi = ylo + btn->h;					if (x >= xlo && x <= xhi && y >= ylo && y <= yhi)					{						fptr = btn->mdfunc;						(*fptr)(ev, btn);						updateScreen();					}				}			}			else if (evtype == SDL_KEYDOWN)			{				if (ev->key.keysym.unicode == SDLK_RETURN)				{					blist = alert->list;					blist = blist->next;					btn = blist->thislist.button;		// get button callback					fptr = btn->mdfunc;					(*fptr)(ev, btn);					updateScreen();				}			}			return;		}	}// No alert or notice is active, scan the list of active widgets// and process the LAST (topmost) widget for which the callback// parameters match.	next = wlist;	last = NULL;	switch (evtype)	{		case SDL_MOUSEBUTTONDOWN:			while (next)			{				m = (MENU *) next->w;				if (m->type == VSliderType || m->type == HSliderType)				{					vs = (VSLIDER *) m;					vs->drag = FALSE;					vs->state = MOUSE_NOT_IN_SLIDER;				}				if (m && m->mdfunc)				{					xlo = m->x;					xhi = xlo + m->w;					ylo = m->y;					yhi = ylo + m->h;					if (x >= xlo && x <= xhi && y >= ylo && y <= yhi)					{						fptr = m->mdfunc;						last = m;					}				}				next = next->next;			}			break;		case SDL_MOUSEBUTTONUP:			if (widget && (widget->p.type == VSliderType || widget->p.type == HSliderType))				timerData.vs = NULL;			while (next)			{				m = (MENU *) next->w;				if (m->type == VSliderType || m->type == HSliderType)				{					vs = (VSLIDER *) m;					vs->drag = FALSE;					vs->state = MOUSE_NOT_IN_SLIDER;				}				if (m && m->mufunc)				{					xlo = m->x;					xhi = xlo + m->w;					ylo = m->y;					yhi = ylo + m->h;					if (x >= xlo && x <= xhi && y >= ylo && y <= yhi)					{						fptr = m->mufunc;						last = m;					}				}				next = next->next;			}			break;		case SDL_MOUSEMOTION:			while (next)			{				m = (MENU *) next->w;				if (m && m->mmfunc)				{					fptr = m->mmfunc;					last = m;					if (m == topWidget)						break;				}				next = next->next;			}			break;		case SDL_KEYDOWN:			while (next)			{				m = (MENU *) next->w;				if (m && m->kdfunc)				{					fptr = m->kdfunc;					last = m;					if (m == topWidget)						break;				}				next = next->next;			}			break;		case SDL_KEYUP:			while (next)			{				m = (MENU *) next->w;				if (m && m->kufunc)				{					fptr = m->kufunc;					last = m;					if (m == topWidget)						break;				}				next = next->next;			}			break;	}	if (fptr)							// fptr points to the last callback that matches, if any	{		if (last->type == VSliderType || last->type == HSliderType)		{			if (evtype != SDL_MOUSEMOTION || ((VSLIDER *) last)->drag)			{				if (last != topWidget)		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -