_HYPlatformPullDown::_HYPlatformPullDown(void) { _HYPullDown * parent = (_HYPullDown*)this; theMenu = gtk_combo_new (); backFill = HYColorToGDKColor((_HYColor) { 255,255,255 }); gtk_combo_set_value_in_list (GTK_COMBO(theMenu),true,false); gtk_container_add(GTK_CONTAINER(parent->parentWindow),theMenu); gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(theMenu)->entry),false); GList* children = gtk_container_get_children(GTK_CONTAINER(theMenu)); g_signal_connect (GTK_WIDGET(children->next->data),"event",(GCallback)hy_pulldown_selection_start_callback_event,(_HYPullDown*)this); g_signal_connect (GTK_COMBO(theMenu)->entry,"changed",(GCallback)hy_pulldown_selection_callback,(_HYPullDown*)this); g_signal_connect (GTK_COMBO(theMenu)->popwin,"hide",(GCallback)hy_pulldown_unmap_event,(_HYPullDown*)this); g_list_free (children); //gtk_container_set_resize_mode(GTK_CONTAINER(theMenu), GTK_RESIZE_IMMEDIATE); selection = 0; cbSelection = -1; if (!defaultPullDownFontPD) { defaultPullDownFontPD = pango_font_description_new(); defaultPullDownFont.size = defaultPullDownFont.size*fontConversionFactor; HYFont2PangoFontDesc (defaultPullDownFont,defaultPullDownFontPD); } gtk_widget_modify_font (theMenu, defaultPullDownFontPD); gtk_widget_modify_font (GTK_COMBO(theMenu)->entry, defaultPullDownFontPD); gtk_widget_show (theMenu); //g_signal_connect (GTK_COMBO(theMenu)->entry,"changed",hy_pulldown_selection_callback,(_HYPullDown*)this); }
_HYPlatformButtonBar::_HYPlatformButtonBar(void) { backFill = HYColorToGDKColor ((_HYColor) { 255,255,255 }); pushed = -1; saveMousePosH = -1; saveMousePosV = -1; lastMouseDown = -1; toolTipBounds.x = 0; theTimer = 0; bbGC = nil; }
//__________________________________________________________________ void _HYPlatformPullDown::_AddMenuItem (_String& newItem, long index) { if (theMenu) { GList * singleItem = g_list_alloc(); singleItem->prev = singleItem->next = nil; if (newItem.Equal(&menuSeparator)) { GtkWidget * itemContents = gtk_separator_menu_item_new (); gtk_widget_show (itemContents); singleItem->data = gtk_list_item_new(); gtk_container_add((GtkContainer*)singleItem->data,itemContents); gtk_combo_set_item_string (GTK_COMBO (theMenu), GTK_ITEM (singleItem->data), ""); gtk_widget_set_sensitive((GtkWidget*)singleItem->data,false); widgetList.InsertElement ((BaseRef)itemContents,2*index,false,false); } else { _String inItem = newItem; if (newItem.beginswith ("(")) { inItem.Trim (1,-1); } GtkWidget * itemContents = gtk_menu_item_new_with_label (inItem.sData); gtk_widget_show (itemContents); singleItem->data = gtk_list_item_new(); gtk_container_add((GtkContainer*)singleItem->data,itemContents); gtk_combo_set_item_string (GTK_COMBO (theMenu), GTK_ITEM (singleItem->data), inItem.sData); gtk_widget_set_sensitive((GtkWidget*)singleItem->data,inItem.sLength == newItem.sLength); widgetList.InsertElement ((BaseRef)itemContents,2*index,false,false); } widgetList.InsertElement ((BaseRef)singleItem->data,2*index,false,false); GdkColor convColor = HYColorToGDKColor(_hyGTKMenuBackground); gtk_widget_modify_bg ((GtkWidget*)singleItem->data, GTK_STATE_INSENSITIVE, &convColor); gtk_widget_show ((GtkWidget*)singleItem->data); if (index<0) { gtk_list_append_items (GTK_LIST (GTK_COMBO (theMenu)->list), singleItem); } else { gtk_list_insert_items (GTK_LIST (GTK_COMBO (theMenu)->list), singleItem, index); } /*printf ("\nAdding menu item %s at %d\n", newItem.sData, index); for (long k = 0; k<widgetList.lLength; k++) printf ("%d %s\n", k, GTK_OBJECT_TYPE_NAME (GTK_WIDGET (widgetList(k))));*/ } if (((_HYPullDown*)this)->MenuItemCount()==1||selection==index) { cbSelection = -1; _RefreshComboBox(); } }
_HYColor SelectAColor (_HYColor& currentColor, _String& prompt) { _HYColor newColor = currentColor; GtkWidget * fileSelector = gtk_color_selection_dialog_new(prompt.sData); GdkColor startColor = HYColorToGDKColor(currentColor); gtk_color_selection_set_current_color (GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(fileSelector)->colorsel), &startColor); g_signal_connect (GTK_COLOR_SELECTION_DIALOG (fileSelector)->ok_button, "clicked", G_CALLBACK (hyphy_kill_dialog_and_exit), fileSelector); g_signal_connect (GTK_COLOR_SELECTION_DIALOG (fileSelector)->colorsel, "color_changed", G_CALLBACK (hyphy_store_color), &newColor); g_signal_connect (GTK_COLOR_SELECTION_DIALOG (fileSelector)->cancel_button, "clicked", G_CALLBACK (hyphy_kill_dialog_and_exit), fileSelector); g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG(fileSelector), "close", G_CALLBACK (hyphy_exit_loop), fileSelector); gtk_widget_show (fileSelector); gtk_window_set_modal (GTK_WINDOW(fileSelector),true); gtk_main (); return newColor; }
bool _HYSequencePane::_ProcessOSEvent (Ptr vEvent) { static bool amScrolling = false, vertical; static long localPt_x, localPt_y, originalStart, originalSpan, lastClick, firstClick; if (_HYPlatformComponent::_ProcessOSEvent (vEvent)) return true; _HY_GTK_UI_Message *theMessage = (_HY_GTK_UI_Message*)vEvent; if (active) { gdouble xc, yc; if (gdk_event_get_coords (theMessage->theEvent,&xc,&yc)) { switch (theMessage->theEvent->type) { case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: { GdkEventButton * bevent = (GdkEventButton*)theMessage->theEvent; long globalPt_x = xc, globalPt_y = yc; localPt_x = globalPt_x-rel.left-parentWindow->allocation.x; localPt_y = globalPt_y-rel.top-parentWindow->allocation.y; vertical = (localPt_x<headerWidth)&&(localPt_y>=(GetSlotHeight()+1)); if (((GdkEventButton*)bevent)->button == 1) { if (vertical) ProcessVSelectionChange (localPt_x,localPt_y,bevent->state & GDK_SHIFT_MASK,bevent->state & GDK_CONTROL_MASK, false, bevent->type == GDK_2BUTTON_PRESS); else ProcessSelectionChange (localPt_x,localPt_y,bevent->state & GDK_SHIFT_MASK,bevent->state & GDK_CONTROL_MASK); } else { if ((((GdkEventButton*)bevent)->button == 2 || ((GdkEventButton*)bevent)->button == 3 )&& (vertical&&vselection.lLength || !vertical &&selection.lLength)) { ProcessContextualPopUp (globalPt_x, globalPt_y); return true; } } } break; case GDK_BUTTON_RELEASE: case GDK_LEAVE_NOTIFY: { if (amScrolling) { if (messageRecipient) ((_HYTWindow*)messageRecipient)->trackMouseComponent = (Ptr)nil; /*gdk_pointer_ungrab (((GdkEventButton*)theMessage->theEvent)->time);*/ if (vertical) { _HYRect invalRectH = {parentWindow->allocation.x+rel.left, parentWindow->allocation.y+rel.top+(GetSlotHeight()+1)+1,rel.left+headerWidth,rel.bottom-HY_SCROLLER_WIDTH}; GdkRectangle irect = HYRect2GDKRect(invalRectH); irect.x+=parentWindow->allocation.x; irect.y+=parentWindow->allocation.y; gdk_window_invalidate_rect (parentWindow->window, &irect, false); if ( localPt_x<headerWidth && localPt_x>0 && lastClick>-2) MoveSpecies (firstClick+originalStart,lastClick+startRow); } amScrolling = false; } break; } case GDK_MOTION_NOTIFY: { GdkEventMotion * motEvent = (GdkEventMotion*)theMessage->theEvent; if (motEvent->state & GDK_BUTTON1_MASK) { if (amScrolling) { gint mousePt_x = motEvent->x - rel.left - parentWindow->allocation.x, mousePt_y = motEvent->y - rel.top - parentWindow->allocation.y; if (vertical) // vertical scrolling { long wHeight = rel.bottom-rel.top-HY_SCROLLER_WIDTH, slotHeight = GetSlotHeight(); if ( mousePt_y < GetSlotHeight()+1 || localPt_y != mousePt_y || mousePt_y>wHeight ) { localPt_x = mousePt_x; localPt_y = mousePt_y; if (mousePt_y>wHeight) { // scroll down if ((endRow<=speciesIndex.lLength)&&(vselection.lData[0]!=speciesIndex.lLength-1)) { if (endRow-startRow<originalSpan) break; startRow++; endRow++; _SetVScrollerPos(((double)MAX_CONTROL_VALUE*startRow)/ (speciesIndex.lLength-endRow+startRow+1)); BuildPane(); forceUpdateForScrolling = true; _MarkForUpdate(); forceUpdateForScrolling = false; lastClick = -2; } break; } else { mousePt_y-=(GetSlotHeight()+1); if (mousePt_y<=slotHeight) { if (mousePt_y>=0) { if (mousePt_y<slotHeight/2) mousePt_y = -1; else mousePt_y = 0; } else { // scroll up if (startRow>0) { startRow--; endRow--; _SetVScrollerPos(((double)MAX_CONTROL_VALUE*startRow)/(speciesIndex.lLength-endRow+startRow+1)); BuildPane(); forceUpdateForScrolling = true; _MarkForUpdate(); forceUpdateForScrolling = false; lastClick = -2; } break; } } else mousePt_y=(mousePt_y-(GetSlotHeight()+1))/slotHeight; } if ( mousePt_y<-1 || mousePt_y>= endRow-startRow ) break; if (mousePt_y!=lastClick) { GdkDrawable * tempDr = GDK_DRAWABLE(parentWindow->window); GdkGC * tempGC = gdk_gc_new (tempDr); GdkColor black = HYColorToGDKColor((_HYColor){0,0,0}); gdk_gc_set_foreground (theContext, &black); gdk_gc_set_function (tempGC, GDK_INVERT); gdk_gc_set_line_attributes (tempGC, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); if (lastClick>=-1) { lastClick = (GetSlotHeight()+1)+slotHeight*(lastClick+1)+rel.top+1; gdk_draw_line (tempDr,tempGC,parentWindow->allocation.x+rel.left+1,parentWindow->allocation.y+lastClick, parentWindow->allocation.x+rel.left+headerWidth-1,parentWindow->allocation.y+lastClick); } lastClick = mousePt_y; if (lastClick+startRow != firstClick+originalStart) { mousePt_y = (GetSlotHeight()+1)+slotHeight*(lastClick+1)+rel.top+1; gdk_draw_line (tempDr,tempGC,parentWindow->allocation.x+rel.left+1,parentWindow->allocation.y+mousePt_y, parentWindow->allocation.x+rel.left+headerWidth-1,parentWindow->allocation.y+mousePt_y); } g_object_unref (tempGC); } } return true; } else // horizontal scrolling { long rightWindowBound = _HYCanvas::GetMaxW()-HY_SCROLLER_WIDTH; guint32 serverTime = gdk_x11_get_server_time (parentWindow->window); if ( mousePt_x<headerWidth && startColumn>0 || localPt_x!=mousePt_x || mousePt_x> rightWindowBound) { forceUpdateForScrolling = true; if (mousePt_x<headerWidth && startColumn>0) { gint wx, wy; gdk_window_get_origin (parentWindow->window,&wx,&wy); wx += parentWindow->allocation.x+rel.left; wy += parentWindow->allocation.y+rel.top; do { guint32 serverTime2 = gdk_x11_get_server_time (parentWindow->window); if (serverTime2-serverTime < 100) ProcessSelectionChange (mousePt_x,mousePt_y,true,true,true); GdkModifierType keyDown; gdk_display_get_pointer (gdk_display_get_default(),NULL,&mousePt_x,&mousePt_y,&keyDown); mousePt_x -= wx; mousePt_y -= wy; serverTime = serverTime2; if ((keyDown & GDK_BUTTON1_MASK)==0) break; gtk_main_iteration_do(true); } while (mousePt_x<headerWidth && startColumn>0); } else { if (mousePt_x> rightWindowBound) { gint wx, wy; gdk_window_get_origin (parentWindow->window,&wx,&wy); wx += parentWindow->allocation.x; wy += parentWindow->allocation.y; do { guint32 serverTime2 = gdk_x11_get_server_time (parentWindow->window); if (serverTime2-serverTime < 100) ProcessSelectionChange (mousePt_x+HY_SCROLLER_WIDTH,mousePt_y,true,true,true); GdkModifierType keyDown; gdk_display_get_pointer (gdk_display_get_default(),NULL,&mousePt_x,&mousePt_y,&keyDown); mousePt_x -= wx; mousePt_y -= wy; serverTime = serverTime2; if ((keyDown & GDK_BUTTON1_MASK)==0) break; gtk_main_iteration_do(true); } while (mousePt_x> rightWindowBound && endColumn < columnStrings.lLength); } else if (serverTime-gdk_event_get_time(theMessage->theEvent) < 100) ProcessSelectionChange (mousePt_x,mousePt_y,true,true,true); } forceUpdateForScrolling = false; localPt_x = mousePt_x; localPt_y = mousePt_y; } return true; } } else { /*gdk_pointer_grab (parentWindow->window,false, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, (((GdkEventMotion*)theMessage->theEvent))->time);*/ if (messageRecipient) ((_HYTWindow*)messageRecipient)->trackMouseComponent = (Ptr)((_HYComponent*)this); amScrolling = true; originalStart = startRow, originalSpan = endRow-startRow; lastClick = -2; firstClick = (localPt_y-(GetSlotHeight()+1))/GetSlotHeight(); return true; } } break; } } } } return false; }
void _HYPlatformGraphicPane::_SetBColor (_HYColor c) { saveBG = HYColorToGDKColor(c); gdk_gc_set_background (theContext, &saveBG); }
void _HYPlatformGraphicPane::_SetColor (_HYColor c) { saveFG = HYColorToGDKColor(c); gdk_gc_set_foreground (theContext, &saveFG); }
void _HYConsoleWindow::_PaintStatusBar(Ptr,bool force) { if (GTK_WIDGET_MAPPED (theWindow)) { _Parameter vL; checkParameter (VerbosityLevelString, vL, 0.0); if (vL<-0.5 && !force) { clock_t curMeasure = clock(); _Parameter diff = 1.0/CLOCKS_PER_SEC*(curMeasure-lastMeasure); if (diff < -vL) { return; } lastMeasure = curMeasure; } if (!stripedFillGC) { SetUpStatusBarStuff (theWindow); } GdkRectangle wRC = {0,0,theWindow->allocation.width,HY_SCROLLER_WIDTH}, w2RC; if (!_hyConsoleWindowGC) { _hyConsoleWindowGC = gdk_gc_new (theWindow->window); gdk_gc_set_tile (_hyConsoleWindowGC, stripedFill); gdk_gc_set_line_attributes(_hyConsoleWindowGC,1,GDK_LINE_SOLID,GDK_CAP_NOT_LAST,GDK_JOIN_MITER); _hyConsoleLayout = pango_layout_new (screenPContext); pango_layout_set_width (_hyConsoleLayout, -1); statusBarBold = pango_font_description_new (); statusBarNormal = pango_font_description_new (); _HYFont consoleFont = {_HY_MONO_FONT,9,HY_FONT_PLAIN}; HYFont2PangoFontDesc (consoleFont,statusBarNormal); consoleFont.style = HY_FONT_BOLD; HYFont2PangoFontDesc (consoleFont,statusBarBold); } GdkPixmap * offBitmap = gdk_pixmap_new (theWindow->window, wRC.width, wRC.height,-1); if (offBitmap) { gdk_gc_set_fill (_hyConsoleWindowGC,GDK_TILED); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,true,-1,-1,wRC.width+2,wRC.height+2); gdk_gc_set_fill (_hyConsoleWindowGC,GDK_SOLID); gdk_gc_set_foreground (_hyConsoleWindowGC,&_BLACKBRUSH_); gdk_draw_line(offBitmap,_hyConsoleWindowGC,0,0,wRC.width,0); pango_layout_set_font_description(_hyConsoleLayout,statusBarNormal); pango_layout_set_text(_hyConsoleLayout,fileName.getStr(),fileName.sLength); gdk_draw_layout(offBitmap,_hyConsoleWindowGC,33,wRC.height-13,_hyConsoleLayout); if (inputStatus == 1) { pango_layout_set_text(_hyConsoleLayout,cInput.getStr(),cInput.sLength); } else { pango_layout_set_text(_hyConsoleLayout,action.getStr(),action.sLength); } gdk_draw_layout(offBitmap,_hyConsoleWindowGC,193,wRC.height-13,_hyConsoleLayout); gdk_gc_set_foreground (_hyConsoleWindowGC,&_DARKGREYBRUSH_); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,true,0,1,30,wRC.height-1); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,true,150,1,40,wRC.height-1); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,true,wRC.width-55,1,55,wRC.height-1); gdk_gc_set_foreground (_hyConsoleWindowGC,&_WHITEBRUSH_); pango_layout_set_font_description(_hyConsoleLayout,statusBarBold); pango_layout_set_text(_hyConsoleLayout,cState.getStr(),cState.sLength); gdk_draw_layout(offBitmap,_hyConsoleWindowGC,3,wRC.height-13,_hyConsoleLayout); pango_layout_set_text(_hyConsoleLayout,cTask.getStr(),cTask.sLength); gdk_draw_layout(offBitmap,_hyConsoleWindowGC,151,wRC.height-13,_hyConsoleLayout); pango_layout_set_font_description(_hyConsoleLayout,statusBarNormal); pango_layout_set_text(_hyConsoleLayout,timer.getStr(),timer.sLength); gdk_draw_layout(offBitmap,_hyConsoleWindowGC,wRC.width-53,wRC.height-13,_hyConsoleLayout); if (percentDone>0 || percentDone == -HY_SL_DONE) { GdkColor blackBrush = HYColorToGDKColor((_HYColor) { 80,80,80 }), orangeBrush = HYColorToGDKColor((_HYColor) { 255,153,102 }); gdk_gc_set_foreground (_hyConsoleWindowGC,&orangeBrush); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,true,wRC.width-135,wRC.height-14,(percentDone>=0?percentDone:100.)*0.75,12); gdk_gc_set_foreground (_hyConsoleWindowGC,&blackBrush); gdk_draw_rectangle (offBitmap,_hyConsoleWindowGC,false,wRC.width-135,wRC.height-14,75,12); //gdk_gc_set_foreground (_hyConsoleWindowGC,&_WHITEBRUSH_); _String pLine; if (percentDone>=0) { pLine = _String(percentDone)&"%"; } else { pLine = "DONE"; } pango_layout_set_text(_hyConsoleLayout,pLine.getStr(),pLine.sLength); gdk_draw_layout(offBitmap,_hyConsoleWindowGC,wRC.width-107,wRC.height-13,_hyConsoleLayout); } } gdk_draw_drawable (theWindow->window, _hyConsoleWindowGC, offBitmap, 0, 0, theWindow->allocation.x, theWindow->allocation.y+theWindow->allocation.height-wRC.height, -1, -1); g_object_unref (offBitmap); } }
*/ #include "HYConsoleWindow.h" #include "HYTextBox.h" #include "HYDialogs.h" #include "HYUtils.h" #include "HYEventTypes.h" #include "time.h" #include "batchlan.h" #include "HYGraphicPane.h" #include "HYDataPanel.h" #include "HYSharedMain.h" GdkColor _DARKGREYBRUSH_ = HYColorToGDKColor((_HYColor) { 100,100,100 }); GdkColor _WHITEBRUSH_ = HYColorToGDKColor((_HYColor) { 255,255,255 }); GdkGC* _hyConsoleWindowGC = nil; PangoLayout* _hyConsoleLayout = nil; PangoFontDescription *statusBarBold, *statusBarNormal; clock_t lastMeasure = 0; #define RECENT_FILE_ITEMS 10
void _HYPlatformPullDown::_SetBackColor (_HYColor& c) { backFill = HYColorToGDKColor(c); }
//__________________________________________________________________ void _HYButtonBar::_DisplayToolTip (void) { // TBI int h = _FindClickedButton (saveMousePosV,saveMousePosH); if ( h>=0 && h<toolTips.lLength) { _String* toolTip = (_String*)toolTips(h); if (toolTip->sLength) { GdkColor toolTipColor = HYColorToGDKColor((_HYColor) { 0xFF,0xCC,0x66 }); int bL, bT; GetButtonLoc (h,bL,bT,false); PangoLayout * ttText = pango_layout_new (screenPContext); PangoFontDescription * ttFont = pango_font_description_new(); HYFont2PangoFontDesc(_hyttDisplayFont,ttFont); pango_layout_set_font_description (ttText, ttFont); pango_layout_set_width(ttText, -1); pango_layout_set_text (ttText, toolTip->sData, toolTip->sLength); PangoRectangle extents; pango_layout_get_pixel_extents (ttText,&extents,nil); toolTipBounds.y = bT - 16; toolTipBounds.height = 16; if (toolTipBounds.y<0) { toolTipBounds.y = bT+buttonDim+1; } h = extents.width + 4; toolTipBounds.x = bL+(buttonDim-h-1)/2; if (toolTipBounds.x<=0) { toolTipBounds.x = 1; } toolTipBounds.width = h+2; h = toolTipBounds.x+toolTipBounds.width-parentWindow->allocation.width; if (h>0) { if (h>=toolTipBounds.x) { h = toolTipBounds.x-1; } toolTipBounds.x -= h; } toolTipBounds.x += parentWindow->allocation.x; toolTipBounds.y += parentWindow->allocation.y; gdk_gc_set_foreground(bbGC,&toolTipColor); gdk_draw_rectangle(parentWindow->window,bbGC,true,toolTipBounds.x, toolTipBounds.y, toolTipBounds.width, toolTipBounds.height); toolTipColor = HYColorToGDKColor((_HYColor) { 0,0,0 }); gdk_gc_set_foreground(bbGC,&toolTipColor); gdk_draw_rectangle(parentWindow->window,bbGC,false,toolTipBounds.x, toolTipBounds.y, toolTipBounds.width, toolTipBounds.height); gdk_gc_set_clip_rectangle (bbGC, &toolTipBounds); gdk_draw_layout (parentWindow->window, bbGC, toolTipBounds.x+3, toolTipBounds.y+3, ttText); gdk_gc_set_clip_rectangle (bbGC, nil); pango_font_description_free (ttFont); g_object_unref (ttText); } } }
void _HYPlatformButtonBar::_SetBackColor (_HYColor& c) { backFill = HYColorToGDKColor(c); }
#include "HYButtonBar.h" #include "HYUtils.h" #include "HYEventTypes.h" #include "HYWindow.h" #include "HYGraphicPane.h" #include "string.h" #ifdef __HYPHYDMALLOC__ #include "dmalloc.h" #endif //__________________________________________________________________ GdkColor buttonBorder1 = HYColorToGDKColor((_HYColor) { 0,0,0 }), buttonBorder2 = HYColorToGDKColor((_HYColor) { 0x3f,0x3f,0x3f }); _HYFont _hyttDisplayFont = {_HY_SANS_FONT,9,HY_FONT_PLAIN}; //__________________________________________________________________ gboolean TooltipPopupTimer (Ptr* userData) { // TBI _HYButtonBar * myBB = (_HYButtonBar*)userData;
void _HYPlatformButton::_SetBackColor (_HYColor& c) { bgColor = HYColorToGDKColor(c); }