зеркало из https://github.com/mozilla/moz-skia.git
371 строка
14 KiB
C++
371 строка
14 KiB
C++
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef SkView_DEFINED
|
|
#define SkView_DEFINED
|
|
|
|
#include "SkEventSink.h"
|
|
#include "SkRect.h"
|
|
#include "SkDOM.h"
|
|
#include "SkTDict.h"
|
|
|
|
class SkCanvas;
|
|
class SkLayerView;
|
|
|
|
/** \class SkView
|
|
|
|
SkView is the base class for screen management. All widgets and controls inherit
|
|
from SkView.
|
|
*/
|
|
class SkView : public SkEventSink {
|
|
public:
|
|
enum Flag_Shift {
|
|
kVisible_Shift,
|
|
kEnabled_Shift,
|
|
kFocusable_Shift,
|
|
kFlexH_Shift,
|
|
kFlexV_Shift,
|
|
kNoClip_Shift,
|
|
|
|
kFlagShiftCount
|
|
};
|
|
enum Flag_Mask {
|
|
kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible
|
|
kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled
|
|
kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus
|
|
kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable
|
|
kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable
|
|
kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds
|
|
|
|
kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)
|
|
};
|
|
|
|
SkView(uint32_t flags = 0);
|
|
virtual ~SkView();
|
|
|
|
/** Return the flags associated with the view
|
|
*/
|
|
uint32_t getFlags() const { return fFlags; }
|
|
/** Set the flags associated with the view
|
|
*/
|
|
void setFlags(uint32_t flags);
|
|
|
|
/** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags
|
|
*/
|
|
int isVisible() const { return fFlags & kVisible_Mask; }
|
|
int isEnabled() const { return fFlags & kEnabled_Mask; }
|
|
int isFocusable() const { return fFlags & kFocusable_Mask; }
|
|
int isClipToBounds() const { return !(fFlags & kNoClip_Mask); }
|
|
/** Helper to set/clear the view's kVisible_Mask flag */
|
|
void setVisibleP(bool);
|
|
void setEnabledP(bool);
|
|
void setFocusableP(bool);
|
|
void setClipToBounds(bool);
|
|
|
|
/** Return the view's width */
|
|
SkScalar width() const { return fWidth; }
|
|
/** Return the view's height */
|
|
SkScalar height() const { return fHeight; }
|
|
/** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */
|
|
void setSize(SkScalar width, SkScalar height);
|
|
void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
|
|
void setWidth(SkScalar width) { this->setSize(width, fHeight); }
|
|
void setHeight(SkScalar height) { this->setSize(fWidth, height); }
|
|
/** Return a rectangle set to [0, 0, width, height] */
|
|
void getLocalBounds(SkRect* bounds) const;
|
|
|
|
/** Return the view's left edge */
|
|
SkScalar locX() const { return fLoc.fX; }
|
|
/** Return the view's top edge */
|
|
SkScalar locY() const { return fLoc.fY; }
|
|
/** Set the view's left and top edge. This does not affect the view's size */
|
|
void setLoc(SkScalar x, SkScalar y);
|
|
void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
|
|
void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
|
|
void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); }
|
|
/** Offset (move) the view by the specified dx and dy. This does not affect the view's size */
|
|
void offset(SkScalar dx, SkScalar dy);
|
|
|
|
/** Call this to have the view draw into the specified canvas. */
|
|
virtual void draw(SkCanvas* canvas);
|
|
|
|
/** Call this to invalidate part of all of a view, requesting that the view's
|
|
draw method be called. The rectangle parameter specifies the part of the view
|
|
that should be redrawn. If it is null, it specifies the entire view bounds.
|
|
*/
|
|
void inval(SkRect* rectOrNull);
|
|
|
|
// Focus management
|
|
|
|
SkView* getFocusView() const;
|
|
bool hasFocus() const;
|
|
|
|
enum FocusDirection {
|
|
kNext_FocusDirection,
|
|
kPrev_FocusDirection,
|
|
|
|
kFocusDirectionCount
|
|
};
|
|
bool acceptFocus();
|
|
SkView* moveFocus(FocusDirection);
|
|
|
|
// Click handling
|
|
|
|
class Click {
|
|
public:
|
|
Click(SkView* target);
|
|
virtual ~Click();
|
|
|
|
const char* getType() const { return fType; }
|
|
bool isType(const char type[]) const;
|
|
void setType(const char type[]); // does NOT make a copy of the string
|
|
void copyType(const char type[]); // makes a copy of the string
|
|
|
|
enum State {
|
|
kDown_State,
|
|
kMoved_State,
|
|
kUp_State
|
|
};
|
|
SkPoint fOrig, fPrev, fCurr;
|
|
SkIPoint fIOrig, fIPrev, fICurr;
|
|
State fState;
|
|
private:
|
|
SkEventSinkID fTargetID;
|
|
char* fType;
|
|
bool fWeOwnTheType;
|
|
|
|
void resetType();
|
|
|
|
friend class SkView;
|
|
};
|
|
Click* findClickHandler(SkScalar x, SkScalar y);
|
|
|
|
static void DoClickDown(Click*, int x, int y);
|
|
static void DoClickMoved(Click*, int x, int y);
|
|
static void DoClickUp(Click*, int x, int y);
|
|
|
|
/** Send the event to the view's parent, and its parent etc. until one of them
|
|
returns true from its onEvent call. This view is returned. If no parent handles
|
|
the event, null is returned.
|
|
*/
|
|
SkView* sendEventToParents(const SkEvent&);
|
|
/** Send the query to the view's parent, and its parent etc. until one of them
|
|
returns true from its onQuery call. This view is returned. If no parent handles
|
|
the query, null is returned.
|
|
*/
|
|
SkView* sendQueryToParents(SkEvent*);
|
|
|
|
/** Depricated helper function. Just call event->post(sinkID, delay);
|
|
*/
|
|
bool postEvent(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) { return evt->post(sinkID, delay); }
|
|
|
|
// View hierarchy management
|
|
|
|
/** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */
|
|
SkView* getParent() const { return fParent; }
|
|
SkView* attachChildToFront(SkView* child);
|
|
/** Attach the child view to this view, and increment the child's reference count. The child view is added
|
|
such that it will be drawn before all other child views.
|
|
The child view parameter is returned.
|
|
*/
|
|
SkView* attachChildToBack(SkView* child);
|
|
/** If the view has a parent, detach the view from its parent and decrement the view's reference count.
|
|
If the parent was the only owner of the view, this will cause the view to be deleted.
|
|
*/
|
|
void detachFromParent();
|
|
/** Attach the child view to this view, and increment the child's reference count. The child view is added
|
|
such that it will be drawn after all other child views.
|
|
The child view parameter is returned.
|
|
*/
|
|
/** Detach all child views from this view. */
|
|
void detachAllChildren();
|
|
|
|
/** Convert the specified point from global coordinates into view-local coordinates
|
|
*/
|
|
void globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); }
|
|
/** Convert the specified x,y from global coordinates into view-local coordinates, returning
|
|
the answer in the local parameter.
|
|
*/
|
|
void globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const;
|
|
|
|
/** \class F2BIter
|
|
|
|
Iterator that will return each of this view's children, in
|
|
front-to-back order (the order used for clicking). The first
|
|
call to next() returns the front-most child view. When
|
|
next() returns null, there are no more child views.
|
|
*/
|
|
class F2BIter {
|
|
public:
|
|
F2BIter(const SkView* parent);
|
|
SkView* next();
|
|
private:
|
|
SkView* fFirstChild, *fChild;
|
|
};
|
|
|
|
/** \class B2FIter
|
|
|
|
Iterator that will return each of this view's children, in
|
|
back-to-front order (the order they are drawn). The first
|
|
call to next() returns the back-most child view. When
|
|
next() returns null, there are no more child views.
|
|
*/
|
|
class B2FIter {
|
|
public:
|
|
B2FIter(const SkView* parent);
|
|
SkView* next();
|
|
private:
|
|
SkView* fFirstChild, *fChild;
|
|
};
|
|
|
|
/** \class Artist
|
|
|
|
Install a subclass of this in a view (calling setArtist()), and then the
|
|
default implementation of that view's onDraw() will invoke this object
|
|
automatically.
|
|
*/
|
|
class Artist : public SkRefCnt {
|
|
public:
|
|
void draw(SkView*, SkCanvas*);
|
|
void inflate(const SkDOM&, const SkDOM::Node*);
|
|
protected:
|
|
virtual void onDraw(SkView*, SkCanvas*) = 0;
|
|
virtual void onInflate(const SkDOM&, const SkDOM::Node*);
|
|
};
|
|
/** Return the artist attached to this view (or null). The artist's reference
|
|
count is not affected.
|
|
*/
|
|
Artist* getArtist() const;
|
|
/** Attach the specified artist (or null) to the view, replacing any existing
|
|
artist. If the new artist is not null, its reference count is incremented.
|
|
The artist parameter is returned.
|
|
*/
|
|
Artist* setArtist(Artist* artist);
|
|
|
|
/** \class Layout
|
|
|
|
Install a subclass of this in a view (calling setLayout()), and then the
|
|
default implementation of that view's onLayoutChildren() will invoke
|
|
this object automatically.
|
|
*/
|
|
class Layout : public SkRefCnt {
|
|
public:
|
|
void layoutChildren(SkView* parent);
|
|
void inflate(const SkDOM&, const SkDOM::Node*);
|
|
protected:
|
|
virtual void onLayoutChildren(SkView* parent) = 0;
|
|
virtual void onInflate(const SkDOM&, const SkDOM::Node*);
|
|
};
|
|
|
|
/** Return the layout attached to this view (or null). The layout's reference
|
|
count is not affected.
|
|
*/
|
|
Layout* getLayout() const;
|
|
/** Attach the specified layout (or null) to the view, replacing any existing
|
|
layout. If the new layout is not null, its reference count is incremented.
|
|
The layout parameter is returned.
|
|
*/
|
|
Layout* setLayout(Layout*, bool invokeLayoutNow = true);
|
|
/** If a layout is attached to this view, call its layoutChildren() method
|
|
*/
|
|
void invokeLayout();
|
|
|
|
/** Call this to initialize this view based on the specified XML node
|
|
*/
|
|
void inflate(const SkDOM& dom, const SkDOM::Node* node);
|
|
/** After a view hierarchy is inflated, this may be called with a dictionary
|
|
containing pairs of <name, view*>, where the name string was the view's
|
|
"id" attribute when it was inflated.
|
|
|
|
This will call the virtual onPostInflate for this view, and the recursively
|
|
call postInflate on all of the view's children.
|
|
*/
|
|
void postInflate(const SkTDict<SkView*>& ids);
|
|
|
|
SkDEBUGCODE(void dump(bool recurse) const;)
|
|
|
|
protected:
|
|
/** Override this to draw inside the view. Be sure to call the inherited version too */
|
|
virtual void onDraw(SkCanvas*);
|
|
/** Override this to be notified when the view's size changes. Be sure to call the inherited version too */
|
|
virtual void onSizeChange();
|
|
/** Override this if you want to handle an inval request from this view or one of its children.
|
|
Tyically this is only overridden by the by the "window". If your subclass does handle the
|
|
request, return true so the request will not continue to propogate to the parent.
|
|
*/
|
|
virtual bool handleInval(const SkRect*);
|
|
//! called once before all of the children are drawn (or clipped/translated)
|
|
virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
|
|
//! called once after all of the children are drawn (or clipped/translated)
|
|
virtual void afterChildren(SkCanvas* orig) {}
|
|
|
|
//! called right before this child's onDraw is called
|
|
virtual void beforeChild(SkView* child, SkCanvas* canvas) {}
|
|
//! called right after this child's onDraw is called
|
|
virtual void afterChild(SkView* child, SkCanvas* canvas) {}
|
|
|
|
/** Override this if you might handle the click
|
|
*/
|
|
virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
|
|
/** Override this to decide if your children are targets for a click.
|
|
The default returns true, in which case your children views will be
|
|
candidates for onFindClickHandler. Returning false wil skip the children
|
|
and just call your onFindClickHandler.
|
|
*/
|
|
virtual bool onSendClickToChildren(SkScalar x, SkScalar y);
|
|
/** Override this to track clicks, returning true as long as you want to track
|
|
the pen/mouse.
|
|
*/
|
|
virtual bool onClick(Click*);
|
|
/** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */
|
|
virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
|
|
/** Override this if you want to perform post initialization work based on the ID dictionary built
|
|
during XML parsing. Be sure to call the inherited version too.
|
|
*/
|
|
virtual void onPostInflate(const SkTDict<SkView*>&);
|
|
|
|
public:
|
|
// default action is to inval the view
|
|
virtual void onFocusChange(bool gainFocusP);
|
|
protected:
|
|
|
|
// override these if you're acting as a layer/host
|
|
virtual bool onGetFocusView(SkView**) const { return false; }
|
|
virtual bool onSetFocusView(SkView*) { return false; }
|
|
|
|
private:
|
|
SkScalar fWidth, fHeight;
|
|
SkPoint fLoc;
|
|
SkView* fParent;
|
|
SkView* fFirstChild;
|
|
SkView* fNextSibling;
|
|
SkView* fPrevSibling;
|
|
uint8_t fFlags;
|
|
uint8_t fContainsFocus;
|
|
|
|
friend class B2FIter;
|
|
friend class F2BIter;
|
|
|
|
friend class SkLayerView;
|
|
|
|
bool setFocusView(SkView* fvOrNull);
|
|
SkView* acceptFocus(FocusDirection);
|
|
void detachFromParent_NoLayout();
|
|
};
|
|
|
|
#endif
|
|
|