зеркало из https://github.com/mozilla/pjs.git
671 строка
19 KiB
C
671 строка
19 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Name: <Xfe/TaskBar.c> */
|
|
/* Description: XfeTaskBar widget source. */
|
|
/* Author: Ramiro Estrugo <ramiro@netscape.com> */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <Xfe/TaskBarP.h>
|
|
|
|
#include <Xfe/Button.h>
|
|
#include <Xfe/Tab.h>
|
|
|
|
#include <Xm/AtomMgr.h>
|
|
#include <Xm/Protocols.h>
|
|
|
|
#define MESSAGE1 "Widget is not an XfeTaskBar."
|
|
#define MESSAGE2 "XmNactionButton is a read-only resource."
|
|
#define MESSAGE3 "XmNfirstWidget is a read-only resource."
|
|
#define MESSAGE4 "XmNrightWidget is a read-only resource."
|
|
#define MESSAGE5 "XmNmaxPosition is too big."
|
|
#define MESSAGE6 "XmNminPosition is too small."
|
|
|
|
#define ACTION_BUTTON_NAME "ActionButton"
|
|
|
|
#define SHADOW_OFFSET 3
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Core Class Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void Initialize (Widget,Widget,ArgList,Cardinal *);
|
|
static void Destroy (Widget);
|
|
static Boolean SetValues (Widget,Widget,Widget,ArgList,
|
|
Cardinal *);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeManager Class Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void PreferredGeometry (Widget,Dimension *,Dimension *);
|
|
static void LayoutComponents (Widget);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeDynamicManager class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void LayoutDynamicChildren (Widget);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Misc XfeTaskBar functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void LayoutComponentsVertical (Widget);
|
|
static void LayoutComponentsHorizontal (Widget);
|
|
static void UpdateActionPixmap (Widget);
|
|
static void UpdateActionCursor (Widget);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Action Button callbacks and event handlers */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void ActionCallback (Widget,XtPointer,XtPointer);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeTaskBar Resources */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static const XtResource resources[] =
|
|
{
|
|
/* Callback resources */
|
|
{
|
|
XmNactionCallback,
|
|
XmCCallback,
|
|
XmRCallback,
|
|
sizeof(XtCallbackList),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_task_bar . action_callback),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
|
|
/* Resources */
|
|
{
|
|
XmNactionButton,
|
|
XmCReadOnly,
|
|
XmRWidget,
|
|
sizeof(Widget),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_task_bar . action_button),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
{
|
|
XmNactionCursor,
|
|
XmCCursor,
|
|
XmRCursor,
|
|
sizeof(Cursor),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_task_bar . action_cursor),
|
|
XmRImmediate,
|
|
(XtPointer) None
|
|
},
|
|
{
|
|
XmNactionPixmap,
|
|
XmCActionPixmap,
|
|
XmRPixmap,
|
|
sizeof(Pixmap),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_task_bar . action_pixmap),
|
|
XmRImmediate,
|
|
(XtPointer) XmUNSPECIFIED_PIXMAP
|
|
},
|
|
{
|
|
XmNshowActionButton,
|
|
XmCShowActionButton,
|
|
XmRBoolean,
|
|
sizeof(Boolean),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_task_bar . show_action_button),
|
|
XmRImmediate,
|
|
(XtPointer) False
|
|
},
|
|
|
|
/* Force all the margins to 0 */
|
|
{
|
|
XmNmarginBottom,
|
|
XmCMarginBottom,
|
|
XmRVerticalDimension,
|
|
sizeof(Dimension),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_manager . margin_bottom),
|
|
XmRImmediate,
|
|
(XtPointer) 0
|
|
},
|
|
{
|
|
XmNmarginLeft,
|
|
XmCMarginLeft,
|
|
XmRHorizontalDimension,
|
|
sizeof(Dimension),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_manager . margin_left),
|
|
XmRImmediate,
|
|
(XtPointer) 0
|
|
},
|
|
{
|
|
XmNmarginRight,
|
|
XmCMarginRight,
|
|
XmRHorizontalDimension,
|
|
sizeof(Dimension),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_manager . margin_right),
|
|
XmRImmediate,
|
|
(XtPointer) 0
|
|
},
|
|
{
|
|
XmNmarginTop,
|
|
XmCMarginTop,
|
|
XmRVerticalDimension,
|
|
sizeof(Dimension),
|
|
XtOffsetOf(XfeTaskBarRec , xfe_manager . margin_top),
|
|
XmRImmediate,
|
|
(XtPointer) 0
|
|
},
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Widget Class Record Initialization */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
_XFE_WIDGET_CLASS_RECORD(taskbar,TaskBar) =
|
|
{
|
|
{
|
|
(WidgetClass) &xfeToolBarClassRec, /* superclass */
|
|
"XfeTaskBar", /* class_name */
|
|
sizeof(XfeTaskBarRec), /* widget_size */
|
|
NULL, /* class_initialize */
|
|
NULL, /* class_part_initiali */
|
|
FALSE, /* class_inited */
|
|
Initialize, /* initialize */
|
|
NULL, /* initialize_hook */
|
|
XtInheritRealize, /* realize */
|
|
NULL, /* actions */
|
|
0, /* num_actions */
|
|
(XtResource *)resources, /* resources */
|
|
XtNumber(resources), /* num_resources */
|
|
NULLQUARK, /* xrm_class */
|
|
TRUE, /* compress_motion */
|
|
XtExposeCompressMaximal, /* compress_exposure */
|
|
TRUE, /* compress_enterleave */
|
|
FALSE, /* visible_interest */
|
|
Destroy, /* destroy */
|
|
XtInheritResize, /* resize */
|
|
XtInheritExpose, /* expose */
|
|
SetValues, /* set_values */
|
|
NULL, /* set_values_hook */
|
|
XtInheritSetValuesAlmost, /* set_values_almost */
|
|
NULL, /* get_values_hook */
|
|
NULL, /* accexfe_focus */
|
|
XtVersion, /* version */
|
|
NULL, /* callback_private */
|
|
XtInheritTranslations, /* tm_table */
|
|
XtInheritQueryGeometry, /* query_geometry */
|
|
XtInheritDisplayAccelerator, /* display accel */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* Composite Part */
|
|
{
|
|
XtInheritGeometryManager, /* geometry_manager */
|
|
XtInheritChangeManaged, /* change_managed */
|
|
XtInheritInsertChild, /* insert_child */
|
|
XtInheritDeleteChild, /* delete_child */
|
|
NULL /* extension */
|
|
},
|
|
|
|
/* Constraint Part */
|
|
{
|
|
NULL, /* resource list */
|
|
0, /* num resources */
|
|
sizeof(XfeToolBarConstraintRec), /* constraint size */
|
|
NULL, /* init proc */
|
|
NULL, /* destroy proc */
|
|
NULL, /* set values proc */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XmManager Part */
|
|
{
|
|
XtInheritTranslations,
|
|
NULL, /* syn resources */
|
|
0, /* num syn_resources */
|
|
NULL, /* syn_cont_resources */
|
|
0, /* num_syn_cont_resource*/
|
|
XmInheritParentProcess, /* parent_process */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfeManager Part */
|
|
{
|
|
XfeInheritBitGravity, /* bit_gravity */
|
|
PreferredGeometry, /* preferred_geometry */
|
|
XfeInheritUpdateBoundary, /* update_boundary */
|
|
XfeInheritUpdateChildrenInfo, /* update_children_info */
|
|
XfeInheritLayoutWidget, /* layout_widget */
|
|
NULL, /* accept_static_child */
|
|
NULL, /* insert_static_child */
|
|
NULL, /* delete_static_child */
|
|
NULL, /* layout_static_children */
|
|
XfeInheritChangeManaged, /* change_managed */
|
|
NULL, /* prepare_components */
|
|
LayoutComponents, /* layout_components */
|
|
NULL, /* draw_background */
|
|
XfeInheritDrawShadow, /* draw_shadow */
|
|
XfeInheritDrawComponents, /* draw_components */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfeDynamicManager Part */
|
|
{
|
|
XfeInheritAcceptDynamicChild, /* accept_dynamic_child */
|
|
XfeInheritInsertDynamicChild, /* insert_dynamic_child */
|
|
XfeInheritDeleteDynamicChild, /* delete_dynamic_child */
|
|
LayoutDynamicChildren, /* layout_dynamic_children */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfeOriented Part */
|
|
{
|
|
NULL, /* enter */
|
|
NULL, /* leave */
|
|
NULL, /* motion */
|
|
NULL, /* drag_start */
|
|
NULL, /* drag_end */
|
|
NULL, /* drag_motion */
|
|
NULL, /* des_enter */
|
|
NULL, /* des_leave */
|
|
NULL, /* des_motion */
|
|
NULL, /* des_drag_start */
|
|
NULL, /* des_drag_end */
|
|
NULL, /* des_drag_motion */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
|
|
/* XfeToolBar Part */
|
|
{
|
|
XfeInheritDrawRaiseBorder, /* draw_raise_border */
|
|
XfeInheritLayoutIndicator, /* layout_indicator */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfeTaskBar Part */
|
|
{
|
|
NULL, /* extension */
|
|
},
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* xfeTaskBarWidgetClass declaration. */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
_XFE_WIDGET_CLASS(taskbar,TaskBar);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Core Class Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
Initialize(Widget rw,Widget nw,ArgList args,Cardinal *nargs)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(nw);
|
|
|
|
/* Create the action button */
|
|
tp->action_button =
|
|
XtVaCreateWidget(ACTION_BUTTON_NAME,
|
|
xfeTabWidgetClass,
|
|
nw,
|
|
XmNmarginLeft, 0,
|
|
XmNmarginRight, 0,
|
|
XmNmarginTop, 0,
|
|
XmNmarginBottom, 0,
|
|
/* XmNprivateComponent, True, */
|
|
XmNtraversalOn, False,
|
|
XmNhighlightThickness, 0,
|
|
XmNarmOffset, 0,
|
|
XmNraiseOffset, 0,
|
|
XmNbackground, _XfeBackgroundPixel(nw),
|
|
NULL);
|
|
|
|
/* Update the pixmaps */
|
|
UpdateActionPixmap(nw);
|
|
|
|
/* Add callback to action button */
|
|
XtAddCallback(tp->action_button,
|
|
XmNactivateCallback,
|
|
ActionCallback,
|
|
(XtPointer) nw);
|
|
|
|
/* Finish of initialization */
|
|
_XfeManagerChainInitialize(rw,nw,xfeTaskBarWidgetClass);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
Destroy(Widget w)
|
|
{
|
|
/* XfeTaskBarPart * tp = _XfeTaskBarPart(w); */
|
|
|
|
/* XtRemoveCallback(tp->action_button, */
|
|
/* XmNactivateCallback, */
|
|
/* ActionCallback, */
|
|
/* (XtPointer) nw); */
|
|
|
|
/* XtRemoveEventHandler(nw, */
|
|
/* StructureNotifyMask, */
|
|
/* True, */
|
|
/* MappingEH, */
|
|
/* (XtPointer) nw); */
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static Boolean
|
|
SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal *nargs)
|
|
{
|
|
XfeTaskBarPart * np = _XfeTaskBarPart(nw);
|
|
XfeTaskBarPart * op = _XfeTaskBarPart(ow);
|
|
|
|
/* action_button */
|
|
if (np->action_button != op->action_button)
|
|
{
|
|
np->action_button = op->action_button;
|
|
}
|
|
|
|
/* action_pixmap */
|
|
if (np->action_pixmap != op->action_pixmap)
|
|
{
|
|
UpdateActionPixmap(nw);
|
|
|
|
_XfemConfigFlags(nw) |= XfeConfigGLE;
|
|
}
|
|
|
|
/* action_cursor */
|
|
if (np->action_cursor != op->action_cursor)
|
|
{
|
|
UpdateActionCursor(nw);
|
|
}
|
|
|
|
/* show_action_button */
|
|
if (np->show_action_button != op->show_action_button)
|
|
{
|
|
_XfemConfigFlags(nw) |= XfeConfigGLE;
|
|
}
|
|
|
|
return _XfeManagerChainSetValues(ow,rw,nw,xfeTaskBarWidgetClass);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeManager Class Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
PreferredGeometry(Widget w,Dimension * width,Dimension * height)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
XfeToolBarWidgetClass tbc = (XfeToolBarWidgetClass)xfeToolBarWidgetClass;
|
|
|
|
(*tbc->xfe_manager_class.preferred_geometry)(w,width,height);
|
|
|
|
if (tp->show_action_button)
|
|
{
|
|
switch (_XfeOrientedOrientation(w))
|
|
{
|
|
case XmHORIZONTAL:
|
|
|
|
*width += _XfeWidth(tp->action_button);
|
|
|
|
break;
|
|
|
|
case XmVERTICAL:
|
|
|
|
*height += _XfeHeight(tp->action_button);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutComponents(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
|
|
/* Invoke layout_indicator method */
|
|
_XfeToolBarLayoutIndicator(w);
|
|
|
|
/* Make sure our one and only component alive and kicking */
|
|
if (!_XfeIsAlive(tp->action_button))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Horizontal */
|
|
if (_XfeOrientedOrientation(w) == XmHORIZONTAL)
|
|
{
|
|
LayoutComponentsHorizontal(w);
|
|
}
|
|
/* Vertical */
|
|
else
|
|
{
|
|
LayoutComponentsVertical(w);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeDynamicManager class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutDynamicChildren(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
Dimension action_width;
|
|
Dimension action_height;
|
|
|
|
if (tp->show_action_button && _XfeIsAlive(tp->action_button))
|
|
{
|
|
action_width = _XfeWidth(tp->action_button);
|
|
action_height = _XfeHeight(tp->action_button);
|
|
}
|
|
else
|
|
{
|
|
action_width = 0;
|
|
action_height = 0;
|
|
}
|
|
|
|
/* Horizontal */
|
|
if (_XfeOrientedOrientation(w) == XmHORIZONTAL)
|
|
{
|
|
/* Add the action button's dimensions to the left margin */
|
|
_XfemMarginLeft(w) += action_width;
|
|
|
|
(*xfeToolBarClassRec.xfe_dynamic_manager_class.layout_dynamic_children)(w);
|
|
|
|
/* Restore the left margin */
|
|
_XfemMarginLeft(w) -= action_width;
|
|
}
|
|
else
|
|
{
|
|
/* Add the action button's dimensions to the top margin */
|
|
_XfemMarginTop(w) += action_height;
|
|
|
|
(*xfeToolBarClassRec.xfe_dynamic_manager_class.layout_dynamic_children)(w);
|
|
|
|
/* Restore the top margin */
|
|
_XfemMarginTop(w) -= action_height;
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Action Button callbacks */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
ActionCallback(Widget child,XtPointer client_data,XtPointer call_data)
|
|
{
|
|
Widget w = XtParent(child);
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
XfeButtonCallbackStruct * cbs = (XfeButtonCallbackStruct *) call_data;
|
|
|
|
if (_XfeIsAlive(w))
|
|
{
|
|
/* Invoke the action callbacks */
|
|
_XfeInvokeCallbacks(w,tp->action_callback,XmCR_ACTION,
|
|
cbs->event,False);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Misc XfeTaskBar functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutComponentsVertical(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
|
|
XtVaSetValues(tp->action_button,
|
|
XmNusePreferredWidth, True,
|
|
NULL);
|
|
|
|
/* Layout the action button */
|
|
_XfeConfigureWidget(tp->action_button,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
_XfeWidth(w),
|
|
|
|
_XfeHeight(tp->action_button));
|
|
|
|
/* Show the action button as needed */
|
|
_XfemIgnoreConfigure(w) = True;
|
|
|
|
if (tp->show_action_button)
|
|
{
|
|
XtManageChild(tp->action_button);
|
|
}
|
|
else
|
|
{
|
|
XtUnmanageChild(tp->action_button);
|
|
}
|
|
|
|
_XfemIgnoreConfigure(w) = False;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutComponentsHorizontal(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
|
|
XtVaSetValues(tp->action_button,
|
|
XmNusePreferredWidth, True,
|
|
NULL);
|
|
|
|
/* Layout the action button */
|
|
_XfeConfigureWidget(tp->action_button,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
_XfeWidth(tp->action_button),
|
|
|
|
_XfeHeight(w));
|
|
|
|
/* Show the action button as needed */
|
|
_XfemIgnoreConfigure(w) = True;
|
|
|
|
if (tp->show_action_button)
|
|
{
|
|
XtManageChild(tp->action_button);
|
|
}
|
|
else
|
|
{
|
|
XtUnmanageChild(tp->action_button);
|
|
}
|
|
|
|
_XfemIgnoreConfigure(w) = False;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
UpdateActionPixmap(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
|
|
if (_XfePixmapGood(tp->action_pixmap))
|
|
{
|
|
XtVaSetValues(tp->action_button,
|
|
XmNpixmap, tp->action_pixmap,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
_XfeResizeWidget(tp->action_button,16,16);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
UpdateActionCursor(Widget w)
|
|
{
|
|
XfeTaskBarPart * tp = _XfeTaskBarPart(w);
|
|
|
|
if (tp->action_pixmap != None)
|
|
{
|
|
XtVaSetValues(tp->action_button,
|
|
XmNcursor, tp->action_cursor,
|
|
XmNcursorOn, True,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
XtVaSetValues(tp->action_button,
|
|
XmNcursor, None,
|
|
XmNcursorOn, False,
|
|
NULL);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeTaskBar Public Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
Widget
|
|
XfeCreateTaskBar(Widget parent,char *name,Arg *args,Cardinal count)
|
|
{
|
|
return (XtCreateWidget(name,xfeTaskBarWidgetClass,parent,args,count));
|
|
}
|
|
/*----------------------------------------------------------------------*/
|