<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 avro_Stream_hh__
#define avro_Stream_hh__

#include <memory>
#include <string.h>
#include <boost/cstdint.hpp>

#include "boost/utility.hpp"

#include "Config.hh"
#include "Exception.hh"

namespace avro {

using boost::uint8_t;

/**
 * A no-copy input stream.
 */
class AVRO_DECL InputStream : boost::noncopyable {
protected:

    /**
     * An empty constuctor.
     */
    InputStream() { }

public:
    /**
     * Destructor.
     */
    virtual ~InputStream() { }

    /**
     * Returns some of available data.
     *
     * Returns true if some data is available, false if no more data is
     * available or an error has occurred.
     */
    virtual bool next(const uint8_t** data, size_t* len) = 0;

    /**
     * "Returns" back some of the data to the stream. The returned
     * data must be less than what was obtained in the last call to
     * next().
     */
    virtual void backup(size_t len) = 0;

    /**
     * Skips number of bytes specified by len.
     */
    virtual void skip(size_t len) = 0;

    /**
     * Returns the number of bytes read from this stream so far.
     * All the bytes made available through next are considered
     * to be used unless, retutned back using backup.
     */
    virtual size_t byteCount() const = 0;
};

/**
 * A no-copy output stream.
 */
class AVRO_DECL OutputStream : boost::noncopyable {
protected:

    /**
     * An empty constuctor.
     */
    OutputStream() { }
public:

    /**
     * Destructor.
     */
    virtual ~OutputStream() { }

    /**
     * Returns a buffer that can be written into.
     * On successful return, data has the pointer to the buffer
     * and len has the number of bytes available at data.
     */
    virtual bool next(uint8_t** data, size_t* len) = 0;

    /**
     * "Returns" back to the stream some of the buffer obtained
     * from in the last call to next().
     */
    virtual void backup(size_t len) = 0;

    /**
     * Number of bytes written so far into this stream. The whole buffer
     * returned by next() is assumed to be written unless some of
     * it was retutned using backup().
     */
    virtual uint64_t byteCount() const = 0;

    /**
     * Flushes any data remaining in the buffer to the stream's underlying
     * store, if any.
     */
    virtual void flush() = 0;
};

/**
 * Returns a new OutputStream, which grows in memory chunks of specified size.
 */
AVRO_DECL std::auto_ptr<OutputStream> memoryOutputStream(size_t chunkSize = 4 * 1024);

/**
 * Returns a new InputStream, with the data from the given byte array.
 * It does not copy the data, the byte array should remain valid
 * until the InputStream is used.
 */
AVRO_DECL std::auto_ptr<InputStream> memoryInputStream(const uint8_t* data, size_t len);

/**
 * Returns a new InputStream with the contents written into an
 * outputstream. The output stream must have been returned by
 * an earlier call to memoryOutputStream(). The contents for the new
 * input stream are the snapshot of the outputstream. One can construct
 * any number of memory input stream from a single memory output stream.
 */
AVRO_DECL std::auto_ptr<InputStream> memoryInputStream(const OutputStream& source);

/**
 * Returns a new OutputStream whose contents would be stored in a file.
 * Data is written in chunks of given buffer size.
 *
 * If there is a file with the given name, it is truncated and overwritten.
 * If there is no file with the given name, it is created.
 */
AVRO_DECL std::auto_ptr<OutputStream> fileOutputStream(const char* filename,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new InputStream whose contents come from the given file.
 * Data is read in chunks of given buffer size.
 */
AVRO_DECL std::auto_ptr<InputStream> fileInputStream(const char* filename,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new OutputStream whose contents will be sent to the given
 * std::ostream. The std::ostream object should outlive the returned
 * OutputStream.
 */
AVRO_DECL std::auto_ptr<OutputStream> ostreamOutputStream(std::ostream& os,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new InputStream whose contents come from the given
 * std::istream. The std::istream object should outlive the returned
 * InputStream.
 */
AVRO_DECL std::auto_ptr<InputStream> istreamInputStream(std::istream& in,
    size_t bufferSize = 8 * 1024);

/** A convenience class for reading from an InputStream */
struct StreamReader {
    /**
     * The underlying input stream.
     */
    InputStream* in_;

    /**
     * The next location to read from.
     */
    const uint8_t* next_;

    /**
     * One past the last valid location.
     */
    const uint8_t* end_;

    /**
     * Constructs an empty reader.
     */
    StreamReader() : in_(0), next_(0), end_(0) { }

    /**
     * Constructs a reader with the given underlying stream.
     */
    StreamReader(InputStream& in) : in_(0), next_(0), end_(0) { reset(in); }

    /**
     * Replaces the current input stream with the given one after backing up
     * the original one if required.
     */
    void reset(InputStream& is) {
        if (in_ != 0 && end_ != next_) {
            in_->backup(end_ - next_);
        }
        in_ = &is;
        next_ = end_ = 0;
    }

    /**
     * Read just one byte from the underlying stream. If there are no
     * more data, throws an exception.
     */
    uint8_t read() {
        if (next_ == end_) {
            more();
        }
        return *next_++;
    }

    /**
     * Reads the given number of bytes from the underlying stream.
     * If there are not that many bytes, throws an exception.
     */
    void readBytes(uint8_t* b, size_t n) {
        while (n > 0) {
            if (next_ == end_) {
                more();
            }
            size_t q = end_ - next_;
            if (q > n) {
                q = n;
            }
            ::memcpy(b, next_, q);
            next_ += q;
            b += q;
            n -= q;
        }
    }

    /**
     * Skips the given number of bytes. Of there are not so that many
     * bytes, throws an exception.
     */
    void skipBytes(size_t n) {
        if (n > static_cast<size_t>(end_ - next_)) {
            n -= end_ - next_;
            next_ = end_;
            in_->skip(n);
        } else {
            next_ += n;
        }
    }

    /**
     * Get as many byes from the underlying stream as possible in a single
     * chunk.
     * \return true if some data could be obtained. False is no more
     * data is available on the stream.
     */
    bool fill() {
        size_t n = 0;
        while (in_->next(&next_, &n)) {
            if (n != 0) {
                end_ = next_ + n;
                return true;
            }
        }
        return false;
    }

    /**
     * Tries to get more data and if it cannot, throws an exception.
     */
    void more() {
        if (! fill()) {
            throw Exception("EOF reached");
        }
    }

    /**
     * Returns true if and only if the end of stream is not reached.
     */
    bool hasMore() {
        return (next_ == end_) ? fill() : true;
    }
};

/**
 * A convinience class to write data into an OutputStream.
 */
struct StreamWriter {
    /**
     * The underlying output stream for this writer.
     */
    OutputStream* out_;

    /**
     * The next location to write to.
     */
    uint8_t* next_;

    /**
     * One past the last location one can write to.
     */
    uint8_t* end_;

    /**
     * Constructs a writer with no underlying stream.
     */
    StreamWriter() : out_(0), next_(0), end_(0) { }

    /**
     * Constructs a new writer with the given underlying stream.
     */
    StreamWriter(OutputStream& out) : out_(0), next_(0), end_(0) { reset(out); }

    /**
     * Replaces the current underlying stream with a new one.
     * If required, it backs up unused bytes in the previous stream.
     */
    void reset(OutputStream& os) {
        if (out_ != 0 && end_ != next_) {
            out_->backup(end_ - next_);
        }
        out_ = &os;
        next_ = end_;
    }

    /**
     * Writes a single byte.
     */
    void write(uint8_t c) {
        if (next_ == end_) {
            more();
        }
        *next_++ = c;
    }

    /**
     * Writes the specified number of bytes starting at \p b.
     */
    void writeBytes(const uint8_t* b, size_t n) {
        while (n > 0) {
            if (next_ == end_) {
                more();
            }
            size_t q = end_ - next_;
            if (q > n) {
                q = n;
            }
            ::memcpy(next_, b, q);
            next_ += q;
            b += q;
            n -= q;
        }
    }

    /**
     * backs up upto the currently written data and flushes the
     * underlying stream.
     */
    void flush() {
        if (next_ != end_) {
            out_->backup(end_ - next_);
            next_ = end_;
        }
        out_->flush();
    }

    /**
     * Gets more space to write to. Throws an exception it cannot.
     */
    void more() {
        size_t n = 0;
        while (out_->next(&next_, &n)) {
            if (n != 0) {
                end_ = next_ + n;
                return;
            }
        }
        throw Exception("EOF reached");
    }

};

/**
 * A convenience function to copy all the contents of an input stream into
 * an output stream.
 */
inline void copy(InputStream& in, OutputStream& out)
{
    const uint8_t *p = 0;
    size_t n = 0;
    StreamWriter w(out);
    while (in.next(&p, &n)) {
        w.writeBytes(p, n);
    }
    w.flush();
}

}   // namespace avro
#endif
<commit_msg>add forgotten using<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 avro_Stream_hh__
#define avro_Stream_hh__

#include <memory>
#include <string.h>
#include <boost/cstdint.hpp>

#include "boost/utility.hpp"

#include "Config.hh"
#include "Exception.hh"

namespace avro {

using boost::uint8_t;
using boost::uint64_t;

/**
 * A no-copy input stream.
 */
class AVRO_DECL InputStream : boost::noncopyable {
protected:

    /**
     * An empty constuctor.
     */
    InputStream() { }

public:
    /**
     * Destructor.
     */
    virtual ~InputStream() { }

    /**
     * Returns some of available data.
     *
     * Returns true if some data is available, false if no more data is
     * available or an error has occurred.
     */
    virtual bool next(const uint8_t** data, size_t* len) = 0;

    /**
     * "Returns" back some of the data to the stream. The returned
     * data must be less than what was obtained in the last call to
     * next().
     */
    virtual void backup(size_t len) = 0;

    /**
     * Skips number of bytes specified by len.
     */
    virtual void skip(size_t len) = 0;

    /**
     * Returns the number of bytes read from this stream so far.
     * All the bytes made available through next are considered
     * to be used unless, retutned back using backup.
     */
    virtual size_t byteCount() const = 0;
};

/**
 * A no-copy output stream.
 */
class AVRO_DECL OutputStream : boost::noncopyable {
protected:

    /**
     * An empty constuctor.
     */
    OutputStream() { }
public:

    /**
     * Destructor.
     */
    virtual ~OutputStream() { }

    /**
     * Returns a buffer that can be written into.
     * On successful return, data has the pointer to the buffer
     * and len has the number of bytes available at data.
     */
    virtual bool next(uint8_t** data, size_t* len) = 0;

    /**
     * "Returns" back to the stream some of the buffer obtained
     * from in the last call to next().
     */
    virtual void backup(size_t len) = 0;

    /**
     * Number of bytes written so far into this stream. The whole buffer
     * returned by next() is assumed to be written unless some of
     * it was retutned using backup().
     */
    virtual uint64_t byteCount() const = 0;

    /**
     * Flushes any data remaining in the buffer to the stream's underlying
     * store, if any.
     */
    virtual void flush() = 0;
};

/**
 * Returns a new OutputStream, which grows in memory chunks of specified size.
 */
AVRO_DECL std::auto_ptr<OutputStream> memoryOutputStream(size_t chunkSize = 4 * 1024);

/**
 * Returns a new InputStream, with the data from the given byte array.
 * It does not copy the data, the byte array should remain valid
 * until the InputStream is used.
 */
AVRO_DECL std::auto_ptr<InputStream> memoryInputStream(const uint8_t* data, size_t len);

/**
 * Returns a new InputStream with the contents written into an
 * outputstream. The output stream must have been returned by
 * an earlier call to memoryOutputStream(). The contents for the new
 * input stream are the snapshot of the outputstream. One can construct
 * any number of memory input stream from a single memory output stream.
 */
AVRO_DECL std::auto_ptr<InputStream> memoryInputStream(const OutputStream& source);

/**
 * Returns a new OutputStream whose contents would be stored in a file.
 * Data is written in chunks of given buffer size.
 *
 * If there is a file with the given name, it is truncated and overwritten.
 * If there is no file with the given name, it is created.
 */
AVRO_DECL std::auto_ptr<OutputStream> fileOutputStream(const char* filename,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new InputStream whose contents come from the given file.
 * Data is read in chunks of given buffer size.
 */
AVRO_DECL std::auto_ptr<InputStream> fileInputStream(const char* filename,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new OutputStream whose contents will be sent to the given
 * std::ostream. The std::ostream object should outlive the returned
 * OutputStream.
 */
AVRO_DECL std::auto_ptr<OutputStream> ostreamOutputStream(std::ostream& os,
    size_t bufferSize = 8 * 1024);

/**
 * Returns a new InputStream whose contents come from the given
 * std::istream. The std::istream object should outlive the returned
 * InputStream.
 */
AVRO_DECL std::auto_ptr<InputStream> istreamInputStream(std::istream& in,
    size_t bufferSize = 8 * 1024);

/** A convenience class for reading from an InputStream */
struct StreamReader {
    /**
     * The underlying input stream.
     */
    InputStream* in_;

    /**
     * The next location to read from.
     */
    const uint8_t* next_;

    /**
     * One past the last valid location.
     */
    const uint8_t* end_;

    /**
     * Constructs an empty reader.
     */
    StreamReader() : in_(0), next_(0), end_(0) { }

    /**
     * Constructs a reader with the given underlying stream.
     */
    StreamReader(InputStream& in) : in_(0), next_(0), end_(0) { reset(in); }

    /**
     * Replaces the current input stream with the given one after backing up
     * the original one if required.
     */
    void reset(InputStream& is) {
        if (in_ != 0 && end_ != next_) {
            in_->backup(end_ - next_);
        }
        in_ = &is;
        next_ = end_ = 0;
    }

    /**
     * Read just one byte from the underlying stream. If there are no
     * more data, throws an exception.
     */
    uint8_t read() {
        if (next_ == end_) {
            more();
        }
        return *next_++;
    }

    /**
     * Reads the given number of bytes from the underlying stream.
     * If there are not that many bytes, throws an exception.
     */
    void readBytes(uint8_t* b, size_t n) {
        while (n > 0) {
            if (next_ == end_) {
                more();
            }
            size_t q = end_ - next_;
            if (q > n) {
                q = n;
            }
            ::memcpy(b, next_, q);
            next_ += q;
            b += q;
            n -= q;
        }
    }

    /**
     * Skips the given number of bytes. Of there are not so that many
     * bytes, throws an exception.
     */
    void skipBytes(size_t n) {
        if (n > static_cast<size_t>(end_ - next_)) {
            n -= end_ - next_;
            next_ = end_;
            in_->skip(n);
        } else {
            next_ += n;
        }
    }

    /**
     * Get as many byes from the underlying stream as possible in a single
     * chunk.
     * \return true if some data could be obtained. False is no more
     * data is available on the stream.
     */
    bool fill() {
        size_t n = 0;
        while (in_->next(&next_, &n)) {
            if (n != 0) {
                end_ = next_ + n;
                return true;
            }
        }
        return false;
    }

    /**
     * Tries to get more data and if it cannot, throws an exception.
     */
    void more() {
        if (! fill()) {
            throw Exception("EOF reached");
        }
    }

    /**
     * Returns true if and only if the end of stream is not reached.
     */
    bool hasMore() {
        return (next_ == end_) ? fill() : true;
    }
};

/**
 * A convinience class to write data into an OutputStream.
 */
struct StreamWriter {
    /**
     * The underlying output stream for this writer.
     */
    OutputStream* out_;

    /**
     * The next location to write to.
     */
    uint8_t* next_;

    /**
     * One past the last location one can write to.
     */
    uint8_t* end_;

    /**
     * Constructs a writer with no underlying stream.
     */
    StreamWriter() : out_(0), next_(0), end_(0) { }

    /**
     * Constructs a new writer with the given underlying stream.
     */
    StreamWriter(OutputStream& out) : out_(0), next_(0), end_(0) { reset(out); }

    /**
     * Replaces the current underlying stream with a new one.
     * If required, it backs up unused bytes in the previous stream.
     */
    void reset(OutputStream& os) {
        if (out_ != 0 && end_ != next_) {
            out_->backup(end_ - next_);
        }
        out_ = &os;
        next_ = end_;
    }

    /**
     * Writes a single byte.
     */
    void write(uint8_t c) {
        if (next_ == end_) {
            more();
        }
        *next_++ = c;
    }

    /**
     * Writes the specified number of bytes starting at \p b.
     */
    void writeBytes(const uint8_t* b, size_t n) {
        while (n > 0) {
            if (next_ == end_) {
                more();
            }
            size_t q = end_ - next_;
            if (q > n) {
                q = n;
            }
            ::memcpy(next_, b, q);
            next_ += q;
            b += q;
            n -= q;
        }
    }

    /**
     * backs up upto the currently written data and flushes the
     * underlying stream.
     */
    void flush() {
        if (next_ != end_) {
            out_->backup(end_ - next_);
            next_ = end_;
        }
        out_->flush();
    }

    /**
     * Gets more space to write to. Throws an exception it cannot.
     */
    void more() {
        size_t n = 0;
        while (out_->next(&next_, &n)) {
            if (n != 0) {
                end_ = next_ + n;
                return;
            }
        }
        throw Exception("EOF reached");
    }

};

/**
 * A convenience function to copy all the contents of an input stream into
 * an output stream.
 */
inline void copy(InputStream& in, OutputStream& out)
{
    const uint8_t *p = 0;
    size_t n = 0;
    StreamWriter w(out);
    while (in.next(&p, &n)) {
        w.writeBytes(p, n);
    }
    w.flush();
}

}   // namespace avro
#endif
<|endoftext|>


<commit_before>/// \file ROOT/TDrawingOptsBase.hxx
/// \ingroup Gpad ROOT7
/// \author Axel Naumann <axel@cern.ch>
/// \date 2017-09-26
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_TDrawingOptsBase
#define ROOT7_TDrawingOptsBase

#include <ROOT/TColor.hxx>

#include <RStringView.h>

#include <map>
#include <string>
#include <vector>

namespace ROOT {
namespace Experimental {
class TCanvas;
class TPadBase;
class TDrawingOptsBaseNoDefault;

namespace Internal {
template <class PRIMITIVE>
class TOptsAttrTable;
}

/** class ROOT::Experimental::TOptsAttrRef
 The `TCanvas` keep track of `TColor`s, integer and floating point attributes used by the drawing options,
 making them accessible from other drawing options. The index into the table of the active attributes is
 wrapped into `TOptsAttrRef` to make them type-safe (i.e. distinct for `TColor`, `long long` and `double`).
 */

template <class PRIMITIVE>
class TOptsAttrRef {
private:
   size_t fIdx = (size_t)-1; ///<! The index in the relevant attribute table of `TCanvas`.

   /// Construct a reference given the index.
   explicit TOptsAttrRef(size_t idx): fIdx(idx) {}

   friend class Internal::TOptsAttrTable<PRIMITIVE>;

public:
   /// Construct an invalid reference.
   TOptsAttrRef() = default;

   /// Construct a reference from its options object, name, and set of string options.
   /// Initialized the PRIMITIVE to the default value, as available in TDrawingOptsBase::GetDefaultCanvas().
   /// The value of this attribute will be the index in the vector of strings; the default value is parsed by
   /// finding the configured string in the vector of strings. `optStrings` will only be used if
   /// `PRIMITIVE` is `long long`.
   TOptsAttrRef(TDrawingOptsBaseNoDefault &opts, std::string_view name,
                const std::vector<std::string_view> &optStrings = {});

   /// Get the underlying index.
   operator size_t() const { return fIdx; }

   /// Whether the reference is valid.
   explicit operator bool() const { return fIdx != (size_t)-1; }
};

extern template class TOptsAttrRef<TColor>;
extern template class TOptsAttrRef<long long>;
extern template class TOptsAttrRef<double>;

namespace Internal {

template <class PRIMITIVE>
class TOptsAttrAndUseCount {
   /// The value.
   PRIMITIVE fVal;
   /// The value's use count.
   size_t fUseCount = 1;

   /// Clear the value; use count must be 0.
   void Clear();

public:
   /// Initialize with a value, setting use count to 1.
   TOptsAttrAndUseCount(const PRIMITIVE &val): fVal(val) {}

   /// Create a value, initializing use count to 1.
   void Create(const PRIMITIVE &val);

   /// Increase the use count; use count must be >= 1 before (i.e. does not create or "resurrect" values).
   void IncrUse();

   /// Decrease the use count; use count must be >= 1 before the call. Calls Clear() if use count drops to 0.
   void DecrUse();

   /// Whether the use count is 0 and this object has space for a new value.
   bool IsFree() const { return fUseCount == 0; }

   /// Value access (non-const).
   PRIMITIVE &Get() { return fVal; }

   /// Value access (const).
   const PRIMITIVE &Get() const { return fVal; }
};

// Only these specializations are used and provided:
extern template class TOptsAttrAndUseCount<TColor>;
extern template class TOptsAttrAndUseCount<long long>;
extern template class TOptsAttrAndUseCount<double>;

template <class PRIMITIVE>
class TOptsAttrTable {
public:
   using value_type = Internal::TOptsAttrAndUseCount<PRIMITIVE>;

private:
   /// Table of attribute primitives. Slots can be freed and re-used.
   /// Drawing options will reference slots in here through their index.
   std::vector<value_type> fTable;

public:
   /// Register an attribute with the table.
   /// \returns the index in the table.
   TOptsAttrRef<PRIMITIVE> Register(const PRIMITIVE &val);

   /// Add a use of the attribute at table index idx.
   void IncrUse(TOptsAttrRef<PRIMITIVE> idx) { fTable[idx].IncrUse(); }

   /// Remove a use of the attribute at table index idx.
   void DecrUse(TOptsAttrRef<PRIMITIVE> idx) { fTable[idx].DecrUse(); }

   /// Update an existing attribute entry in the table.
   void Update(TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val) { fTable[idx] = val; }

   /// Get the value at index `idx` (const version).
   const PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> idx) const { return fTable[idx].Get(); }

   /// Get the value at index `idx` (non-const version).
   PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> idx) { return fTable[idx].Get(); }

   /// Find the index belonging to the attribute at the given address and add a use.
   /// \returns the reference to `val`, which might be `IsInvalid()` if `val` is not part of this table.
   TOptsAttrRef<PRIMITIVE> SameAs(const PRIMITIVE &val);

   /// Access to the underlying attribute table (non-const version).
   std::vector<value_type> &GetTable() { return fTable; }

   /// Access to the underlying attribute table (const version).
   const std::vector<value_type> &GetTable() const { return fTable; }
};

extern template class TOptsAttrTable<TColor>;
extern template class TOptsAttrTable<long long>;
extern template class TOptsAttrTable<double>;
} // namespace Internal

/** \class ROOT::Experimental::TDrawingOptsBase
  Base class for drawing options. Implements access to the default and the default's initialization
  from a config file.

  Drawing options are made up of three kinds of primitives:
    - TColor
    - integer (long long)
    - floating point (double)
  They register the primitives with their `TCanvas`, and then refer to the registered primitives.
  Upon destruction, the `TDrawingOptsBase` deregisters the use of its primitives with the `TCanvas`,
  which empties the respective slots in the tables of the `TCanvas`, unless other options reference
  the same primitives (through `SameAs()`), and until the last use has deregistered.

  In derived classes (e.g. drawing options for the class `MyFancyBox`), declare attribute members as
     TOptsAttrRef<TColor> fLineColor{*this, "MyFancyBox.LineColor"};
  The attribute's value will be taken from the  will be initialized
  */

class TDrawingOptsBaseNoDefault {
public:
   template <class PRIMITIVE>
   class OptsAttrRefArr {
      /// Indexes of the `TCanvas`'s attribute table entries used by the options object.
      std::vector<TOptsAttrRef<PRIMITIVE>> fRefArray;

   public:
      ~OptsAttrRefArr();
      /// Register an attribute.
      ///\returns the index of the new attribute.
      TOptsAttrRef<PRIMITIVE> Register(TCanvas &canv, const PRIMITIVE &val);

      /// Re-use an existing attribute.
      ///\returns the index of the attribute (i.e. valRef).
      TOptsAttrRef<PRIMITIVE> SameAs(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx);

      /// Re-use an existing attribute.
      ///\returns the index of the attribute, might be `IsInvalid()` if `val` could not be found.
      TOptsAttrRef<PRIMITIVE> SameAs(TCanvas &canv, const PRIMITIVE &val);

      /// Update the attribute at index `idx` to the value `val`.
      void Update(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val);

      /// Clear all attribute references, removing their uses in `TCanvas`.
      void Release(TCanvas &canv);

      /// Once copied, elements of a OptsAttrRefArr need to increase their use count.
      void RegisterCopy(TCanvas &canv);

      /// Access to attribute (const version).
      const PRIMITIVE &Get(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx) const;

      /// Access to attribute (non-const version).
      PRIMITIVE &Get(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx);
   };

private:
   /// The `TCanvas` holding the `TDrawable` (or its `TPad`).
   TCanvas *fCanvas; //-> always != nullptr

   /// Indexes of the `TCanvas`'s color table entries used by this options object.
   OptsAttrRefArr<TColor> fColorIdx;

   /// Indexes of the `TCanvas`'s integer table entries used by this options object.
   OptsAttrRefArr<long long> fIntIdx;

   /// Indexes of the `TCanvas`'s floating point table entries used by this options object.
   OptsAttrRefArr<double> fFPIdx;

   /// Access to the attribute tables (non-const version).
   OptsAttrRefArr<TColor> &GetAttrsRefArr(TColor *) { return fColorIdx; }
   OptsAttrRefArr<long long> &GetAttrsRefArr(long long *) { return fIntIdx; }
   OptsAttrRefArr<double> &GetAttrsRefArr(double *) { return fFPIdx; }

   /// Access to the attribute tables (const version).
   const OptsAttrRefArr<TColor> &GetAttrsRefArr(TColor *) const { return fColorIdx; }
   const OptsAttrRefArr<long long> &GetAttrsRefArr(long long *) const { return fIntIdx; }
   const OptsAttrRefArr<double> &GetAttrsRefArr(double *) const { return fFPIdx; }

protected:
   /// Construct from the pad that holds our `TDrawable`.
   TDrawingOptsBaseNoDefault(TPadBase &pad);

   /// Default attributes need to register their values in a pad - they will take this pad!
   static TPadBase &GetDefaultCanvas();

   /// The `TCanvas` holding the `TDrawable` (or its `TPad`) (non-const version).
   TCanvas &GetCanvas() { return *fCanvas; }

   /// The `TCanvas` holding the `TDrawable` (or its `TPad`) (const version).
   const TCanvas &GetCanvas() const { return *fCanvas; }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> Register(const PRIMITIVE &val)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).Register(GetCanvas(), val);
   }

   template <class PRIMITIVE>
   void Update(TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val)
   {
      GetAttrsRefArr((PRIMITIVE *)nullptr).Update(GetCanvas(), idx, val);
   }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> SameAs(TOptsAttrRef<PRIMITIVE> idx)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).SameAs(GetCanvas(), idx);
   }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> SameAs(const PRIMITIVE &val)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).SameAs(GetCanvas(), val);
   }

   template <class PRIMITIVE>
   friend class TOptsAttrRef;

public:
   ~TDrawingOptsBaseNoDefault();
   TDrawingOptsBaseNoDefault(const TDrawingOptsBaseNoDefault &other);
   TDrawingOptsBaseNoDefault(TDrawingOptsBaseNoDefault &&other) = default;

   /// Access to the attribute (non-const version).
   template <class PRIMITIVE>
   PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> ref) { return GetAttrsRefArr((PRIMITIVE*)nullptr).Get(GetCanvas(), ref); }
   /// Access to the attribute (const version).
   template <class PRIMITIVE>
   const PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> ref) const { return GetAttrsRefArr((PRIMITIVE*)nullptr).Get(GetCanvas(), ref); }
};

extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<TColor>;
extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<long long>;
extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<double>;

template <class DERIVED>
class TDrawingOptsBase: public TDrawingOptsBaseNoDefault {
public:
   /// Construct from the pad that holds our `TDrawable`.
   TDrawingOptsBase(TPadBase &pad): TDrawingOptsBaseNoDefault(pad)
   {
      if (&pad != &GetDefaultCanvas())
         Default();
   }

   /// Retrieve the default drawing options for `DERIVED`. Can be used to query and adjust the
   /// default options.
   static DERIVED &Default()
   {
      static DERIVED defaultOpts(GetDefaultCanvas());
      return defaultOpts;
   }
};

} // namespace Experimental
} // namespace ROOT

#endif
<commit_msg>Allow TOptsAttrAndUseCount, TDrawingOptsBaseNoDefault, TDrawingOptsBase to be default constructed.<commit_after>/// \file ROOT/TDrawingOptsBase.hxx
/// \ingroup Gpad ROOT7
/// \author Axel Naumann <axel@cern.ch>
/// \date 2017-09-26
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_TDrawingOptsBase
#define ROOT7_TDrawingOptsBase

#include <ROOT/TColor.hxx>

#include <RStringView.h>

#include <map>
#include <string>
#include <vector>

namespace ROOT {
namespace Experimental {
class TCanvas;
class TPadBase;
class TDrawingOptsBaseNoDefault;

namespace Internal {
template <class PRIMITIVE>
class TOptsAttrTable;
}

/** class ROOT::Experimental::TOptsAttrRef
 The `TCanvas` keep track of `TColor`s, integer and floating point attributes used by the drawing options,
 making them accessible from other drawing options. The index into the table of the active attributes is
 wrapped into `TOptsAttrRef` to make them type-safe (i.e. distinct for `TColor`, `long long` and `double`).
 */

template <class PRIMITIVE>
class TOptsAttrRef {
private:
   size_t fIdx = (size_t)-1; ///<! The index in the relevant attribute table of `TCanvas`.

   /// Construct a reference given the index.
   explicit TOptsAttrRef(size_t idx): fIdx(idx) {}

   friend class Internal::TOptsAttrTable<PRIMITIVE>;

public:
   /// Construct an invalid reference.
   TOptsAttrRef() = default;

   /// Construct a reference from its options object, name, and set of string options.
   /// Initialized the PRIMITIVE to the default value, as available in TDrawingOptsBase::GetDefaultCanvas().
   /// The value of this attribute will be the index in the vector of strings; the default value is parsed by
   /// finding the configured string in the vector of strings. `optStrings` will only be used if
   /// `PRIMITIVE` is `long long`.
   TOptsAttrRef(TDrawingOptsBaseNoDefault &opts, std::string_view name,
                const std::vector<std::string_view> &optStrings = {});

   /// Get the underlying index.
   operator size_t() const { return fIdx; }

   /// Whether the reference is valid.
   explicit operator bool() const { return fIdx != (size_t)-1; }
};

extern template class TOptsAttrRef<TColor>;
extern template class TOptsAttrRef<long long>;
extern template class TOptsAttrRef<double>;

namespace Internal {

template <class PRIMITIVE>
class TOptsAttrAndUseCount {
   /// The value.
   PRIMITIVE fVal;
   /// The value's use count.
   size_t fUseCount = 1;

   /// Clear the value; use count must be 0.
   void Clear();

public:
   /// Default constructor: a default-constructed value that is unused.
   TOptsAttrAndUseCount(): fVal(), fUseCount(0) {}

   /// Initialize with a value, setting use count to 1.
   TOptsAttrAndUseCount(const PRIMITIVE &val): fVal(val) {}

   /// Create a value, initializing use count to 1.
   void Create(const PRIMITIVE &val);

   /// Increase the use count; use count must be >= 1 before (i.e. does not create or "resurrect" values).
   void IncrUse();

   /// Decrease the use count; use count must be >= 1 before the call. Calls Clear() if use count drops to 0.
   void DecrUse();

   /// Whether the use count is 0 and this object has space for a new value.
   bool IsFree() const { return fUseCount == 0; }

   /// Value access (non-const).
   PRIMITIVE &Get() { return fVal; }

   /// Value access (const).
   const PRIMITIVE &Get() const { return fVal; }
};

// Only these specializations are used and provided:
extern template class TOptsAttrAndUseCount<TColor>;
extern template class TOptsAttrAndUseCount<long long>;
extern template class TOptsAttrAndUseCount<double>;

template <class PRIMITIVE>
class TOptsAttrTable {
public:
   using value_type = Internal::TOptsAttrAndUseCount<PRIMITIVE>;

private:
   /// Table of attribute primitives. Slots can be freed and re-used.
   /// Drawing options will reference slots in here through their index.
   std::vector<value_type> fTable;

public:
   /// Register an attribute with the table.
   /// \returns the index in the table.
   TOptsAttrRef<PRIMITIVE> Register(const PRIMITIVE &val);

   /// Add a use of the attribute at table index idx.
   void IncrUse(TOptsAttrRef<PRIMITIVE> idx) { fTable[idx].IncrUse(); }

   /// Remove a use of the attribute at table index idx.
   void DecrUse(TOptsAttrRef<PRIMITIVE> idx) { fTable[idx].DecrUse(); }

   /// Update an existing attribute entry in the table.
   void Update(TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val) { fTable[idx] = val; }

   /// Get the value at index `idx` (const version).
   const PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> idx) const { return fTable[idx].Get(); }

   /// Get the value at index `idx` (non-const version).
   PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> idx) { return fTable[idx].Get(); }

   /// Find the index belonging to the attribute at the given address and add a use.
   /// \returns the reference to `val`, which might be `IsInvalid()` if `val` is not part of this table.
   TOptsAttrRef<PRIMITIVE> SameAs(const PRIMITIVE &val);

   /// Access to the underlying attribute table (non-const version).
   std::vector<value_type> &GetTable() { return fTable; }

   /// Access to the underlying attribute table (const version).
   const std::vector<value_type> &GetTable() const { return fTable; }
};

extern template class TOptsAttrTable<TColor>;
extern template class TOptsAttrTable<long long>;
extern template class TOptsAttrTable<double>;
} // namespace Internal

/** \class ROOT::Experimental::TDrawingOptsBase
  Base class for drawing options. Implements access to the default and the default's initialization
  from a config file.

  Drawing options are made up of three kinds of primitives:
    - TColor
    - integer (long long)
    - floating point (double)
  They register the primitives with their `TCanvas`, and then refer to the registered primitives.
  Upon destruction, the `TDrawingOptsBase` deregisters the use of its primitives with the `TCanvas`,
  which empties the respective slots in the tables of the `TCanvas`, unless other options reference
  the same primitives (through `SameAs()`), and until the last use has deregistered.

  In derived classes (e.g. drawing options for the class `MyFancyBox`), declare attribute members as
     TOptsAttrRef<TColor> fLineColor{*this, "MyFancyBox.LineColor"};
  The attribute's value will be taken from the  will be initialized
  */

class TDrawingOptsBaseNoDefault {
public:
   template <class PRIMITIVE>
   class OptsAttrRefArr {
      /// Indexes of the `TCanvas`'s attribute table entries used by the options object.
      std::vector<TOptsAttrRef<PRIMITIVE>> fRefArray;

   public:
      ~OptsAttrRefArr();
      /// Register an attribute.
      ///\returns the index of the new attribute.
      TOptsAttrRef<PRIMITIVE> Register(TCanvas &canv, const PRIMITIVE &val);

      /// Re-use an existing attribute.
      ///\returns the index of the attribute (i.e. valRef).
      TOptsAttrRef<PRIMITIVE> SameAs(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx);

      /// Re-use an existing attribute.
      ///\returns the index of the attribute, might be `IsInvalid()` if `val` could not be found.
      TOptsAttrRef<PRIMITIVE> SameAs(TCanvas &canv, const PRIMITIVE &val);

      /// Update the attribute at index `idx` to the value `val`.
      void Update(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val);

      /// Clear all attribute references, removing their uses in `TCanvas`.
      void Release(TCanvas &canv);

      /// Once copied, elements of a OptsAttrRefArr need to increase their use count.
      void RegisterCopy(TCanvas &canv);

      /// Access to attribute (const version).
      const PRIMITIVE &Get(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx) const;

      /// Access to attribute (non-const version).
      PRIMITIVE &Get(TCanvas &canv, TOptsAttrRef<PRIMITIVE> idx);
   };

private:
   /// The `TCanvas` holding the `TDrawable` (or its `TPad`).
   TCanvas *fCanvas = nullptr;

   /// Indexes of the `TCanvas`'s color table entries used by this options object.
   OptsAttrRefArr<TColor> fColorIdx;

   /// Indexes of the `TCanvas`'s integer table entries used by this options object.
   OptsAttrRefArr<long long> fIntIdx;

   /// Indexes of the `TCanvas`'s floating point table entries used by this options object.
   OptsAttrRefArr<double> fFPIdx;

   /// Access to the attribute tables (non-const version).
   OptsAttrRefArr<TColor> &GetAttrsRefArr(TColor *) { return fColorIdx; }
   OptsAttrRefArr<long long> &GetAttrsRefArr(long long *) { return fIntIdx; }
   OptsAttrRefArr<double> &GetAttrsRefArr(double *) { return fFPIdx; }

   /// Access to the attribute tables (const version).
   const OptsAttrRefArr<TColor> &GetAttrsRefArr(TColor *) const { return fColorIdx; }
   const OptsAttrRefArr<long long> &GetAttrsRefArr(long long *) const { return fIntIdx; }
   const OptsAttrRefArr<double> &GetAttrsRefArr(double *) const { return fFPIdx; }

protected:
   /// Construct from the pad that holds our `TDrawable`.
   TDrawingOptsBaseNoDefault(TPadBase &pad);

   /// Default attributes need to register their values in a pad - they will take this pad!
   static TPadBase &GetDefaultCanvas();

   /// The `TCanvas` holding the `TDrawable` (or its `TPad`) (non-const version).
   TCanvas &GetCanvas() { return *fCanvas; }

   /// The `TCanvas` holding the `TDrawable` (or its `TPad`) (const version).
   const TCanvas &GetCanvas() const { return *fCanvas; }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> Register(const PRIMITIVE &val)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).Register(GetCanvas(), val);
   }

   template <class PRIMITIVE>
   void Update(TOptsAttrRef<PRIMITIVE> idx, const PRIMITIVE &val)
   {
      GetAttrsRefArr((PRIMITIVE *)nullptr).Update(GetCanvas(), idx, val);
   }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> SameAs(TOptsAttrRef<PRIMITIVE> idx)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).SameAs(GetCanvas(), idx);
   }

   template <class PRIMITIVE>
   TOptsAttrRef<PRIMITIVE> SameAs(const PRIMITIVE &val)
   {
      return GetAttrsRefArr((PRIMITIVE *)nullptr).SameAs(GetCanvas(), val);
   }

   template <class PRIMITIVE>
   friend class TOptsAttrRef;

public:
   TDrawingOptsBaseNoDefault() = default;
   ~TDrawingOptsBaseNoDefault();
   TDrawingOptsBaseNoDefault(const TDrawingOptsBaseNoDefault &other);
   TDrawingOptsBaseNoDefault(TDrawingOptsBaseNoDefault &&other) = default;

   /// Access to the attribute (non-const version).
   template <class PRIMITIVE>
   PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> ref) { return GetAttrsRefArr((PRIMITIVE*)nullptr).Get(GetCanvas(), ref); }
   /// Access to the attribute (const version).
   template <class PRIMITIVE>
   const PRIMITIVE &Get(TOptsAttrRef<PRIMITIVE> ref) const { return GetAttrsRefArr((PRIMITIVE*)nullptr).Get(GetCanvas(), ref); }
};

extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<TColor>;
extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<long long>;
extern template class TDrawingOptsBaseNoDefault::OptsAttrRefArr<double>;

template <class DERIVED>
class TDrawingOptsBase: public TDrawingOptsBaseNoDefault {
public:
   TDrawingOptsBase() = default;
   /// Construct from the pad that holds our `TDrawable`.
   TDrawingOptsBase(TPadBase &pad): TDrawingOptsBaseNoDefault(pad)
   {
      if (&pad != &GetDefaultCanvas())
         Default();
   }

   /// Retrieve the default drawing options for `DERIVED`. Can be used to query and adjust the
   /// default options.
   static DERIVED &Default()
   {
      static DERIVED defaultOpts(GetDefaultCanvas());
      return defaultOpts;
   }
};

} // namespace Experimental
} // namespace ROOT

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/extensions/file_browser_notifications.h"

#include <gtest/gtest.h>
#include <string>

#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"

namespace chromeos {

class MockFileBrowserNotifications : public FileBrowserNotifications {
 public:
  explicit MockFileBrowserNotifications(Profile* profile)
      : FileBrowserNotifications(profile) {
  }
  virtual ~MockFileBrowserNotifications() {}

  // Records the notification so we can force it to show later.
  virtual void PostDelayedShowNotificationTask(
      const std::string& notification_id,
      NotificationType type,
      const string16&  message,
      size_t delay_ms) OVERRIDE {
    show_callback_data_.id = notification_id;
    show_callback_data_.type = type;
    show_callback_data_.message = message;
  }

  // Records the notification so we can force it to hide later.
  virtual void PostDelayedHideNotificationTask(NotificationType type,
                                               const std::string  path,
                                               size_t delay_ms) OVERRIDE {
    hide_callback_data_.type = type;
    hide_callback_data_.path = path;
  }

  void ExecuteShow() {
    FileBrowserNotifications::ShowNotificationDelayedTask(
      show_callback_data_.id, show_callback_data_.type,
      show_callback_data_.message, AsWeakPtr());
  }

  void ExecuteHide() {
    FileBrowserNotifications::HideNotificationDelayedTask(
      hide_callback_data_.type, hide_callback_data_.path, AsWeakPtr());
  }

 private:
  struct ShowCallbackData {
    std::string id;
    NotificationType type;
    string16 message;
  };

  ShowCallbackData show_callback_data_;

  struct HideCallbackData {
    NotificationType type;
    std::string path;
  };

  HideCallbackData hide_callback_data_;
};

class FileBrowserNotificationsTest : public InProcessBrowserTest {
 public:
  FileBrowserNotificationsTest() : collection_(NULL) {}

 protected:
  // This must be initialized late in test startup.
  void InitNotifications() {
    Profile* profile = browser()->profile();
    notifications_.reset(new MockFileBrowserNotifications(profile));
    collection_ =
        g_browser_process->notification_ui_manager()->balloon_collection();
  }

  bool FindNotification(const std::string& id) {
    return notifications_->notifications().find(id) !=
           notifications_->notifications().end();
  }

  bool FindBalloon(const std::string& id) {
    const std::deque<Balloon*>& balloons = collection_->GetActiveBalloons();
    for (std::deque<Balloon*>::const_iterator it = balloons.begin();
         it != balloons.end();
         ++it) {
      Balloon* balloon = *it;
      if (balloon->notification().notification_id() == id)
        return true;
    }
    return false;
  }

  BalloonCollection* collection_;
  scoped_ptr<MockFileBrowserNotifications> notifications_;
};

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_TestBasic FAILS_TestBasic
#else
#define MAYBE_TestBasic TestBasic
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_TestBasic) {
  InitNotifications();
  // We start with no balloons.
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Showing a notification both updates our data and shows a balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Updating the same notification maintains the same balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // A new notification adds a new balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(2u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("DFpath"));
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Hiding a notification removes it from our data.
  notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_FALSE(FindNotification("DFpath"));
  EXPECT_TRUE(FindNotification("Dpath"));

  // Balloons don't go away until we run the message loop.
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Running the message loop allows the balloon to disappear.
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_FALSE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));
};

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_ShowDelayedTest FAILS_ShowDelayedTest
#else
// TODO(jamescook): This test is flaky on linux_chromeos, occasionally causing
// this assertion failure inside Gtk:
//   "murrine_style_draw_box: assertion `height >= -1' failed"
// There may be an underlying bug in the ChromeOS notification code.
// I'm not marking it as FLAKY because this doesn't happen on the bots.
#define MAYBE_ShowDelayedTest ShowDelayedTest
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_ShowDelayedTest) {
  InitNotifications();
  // Adding a delayed notification does not show a balloon.
  notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE,
                                          "path", 3000);
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Forcing the show to happen makes the balloon appear.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Showing a notification both immediately and delayed results in one
  // additional balloon.
  notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL,
                                          "path", 3000);
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));

  // When the delayed notification arrives, it's an update, so we still only
  // have two balloons.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));

  // If we schedule a show for later, then hide before it becomes visible,
  // the balloon should not be added.
  notifications_->ShowNotificationDelayed(
      FileBrowserNotifications::FORMAT_FAIL, "path", 3000);
  notifications_->HideNotification(FileBrowserNotifications::FORMAT_FAIL,
                                   "path");
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_FALSE(FindBalloon("Fpath"));

  // Even when we try to force the show, nothing appears, because the balloon
  // was explicitly hidden.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_FALSE(FindBalloon("Fpath"));
}

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_HideDelayedTest FAILS_HideDelayedTest
#else
#define MAYBE_HideDelayedTest HideDelayedTest
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_HideDelayedTest) {
  InitNotifications();
  // Showing now, and scheduling a hide for later, results in one balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE,
                                          "path", 3000);
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Forcing the hide removes the balloon.
  notifications_->ExecuteHide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Immediate show then hide results in no balloons.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Delayed hide for a notification that doesn't exist does nothing.
  notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL,
                                          "path", 3000);
  notifications_->ExecuteHide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());
}

}  // namespace chromeos.
<commit_msg>Aura: Mark FileBrowserNotificationsTest disabled for now<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/extensions/file_browser_notifications.h"

#include <gtest/gtest.h>
#include <string>

#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"

namespace chromeos {

class MockFileBrowserNotifications : public FileBrowserNotifications {
 public:
  explicit MockFileBrowserNotifications(Profile* profile)
      : FileBrowserNotifications(profile) {
  }
  virtual ~MockFileBrowserNotifications() {}

  // Records the notification so we can force it to show later.
  virtual void PostDelayedShowNotificationTask(
      const std::string& notification_id,
      NotificationType type,
      const string16&  message,
      size_t delay_ms) OVERRIDE {
    show_callback_data_.id = notification_id;
    show_callback_data_.type = type;
    show_callback_data_.message = message;
  }

  // Records the notification so we can force it to hide later.
  virtual void PostDelayedHideNotificationTask(NotificationType type,
                                               const std::string  path,
                                               size_t delay_ms) OVERRIDE {
    hide_callback_data_.type = type;
    hide_callback_data_.path = path;
  }

  void ExecuteShow() {
    FileBrowserNotifications::ShowNotificationDelayedTask(
      show_callback_data_.id, show_callback_data_.type,
      show_callback_data_.message, AsWeakPtr());
  }

  void ExecuteHide() {
    FileBrowserNotifications::HideNotificationDelayedTask(
      hide_callback_data_.type, hide_callback_data_.path, AsWeakPtr());
  }

 private:
  struct ShowCallbackData {
    std::string id;
    NotificationType type;
    string16 message;
  };

  ShowCallbackData show_callback_data_;

  struct HideCallbackData {
    NotificationType type;
    std::string path;
  };

  HideCallbackData hide_callback_data_;
};

class FileBrowserNotificationsTest : public InProcessBrowserTest {
 public:
  FileBrowserNotificationsTest() : collection_(NULL) {}

 protected:
  // This must be initialized late in test startup.
  void InitNotifications() {
    Profile* profile = browser()->profile();
    notifications_.reset(new MockFileBrowserNotifications(profile));
    collection_ =
        g_browser_process->notification_ui_manager()->balloon_collection();
  }

  bool FindNotification(const std::string& id) {
    return notifications_->notifications().find(id) !=
           notifications_->notifications().end();
  }

  bool FindBalloon(const std::string& id) {
    const std::deque<Balloon*>& balloons = collection_->GetActiveBalloons();
    for (std::deque<Balloon*>::const_iterator it = balloons.begin();
         it != balloons.end();
         ++it) {
      Balloon* balloon = *it;
      if (balloon->notification().notification_id() == id)
        return true;
    }
    return false;
  }

  BalloonCollection* collection_;
  scoped_ptr<MockFileBrowserNotifications> notifications_;
};

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_TestBasic DISABLED_TestBasic
#else
#define MAYBE_TestBasic TestBasic
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_TestBasic) {
  InitNotifications();
  // We start with no balloons.
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Showing a notification both updates our data and shows a balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Updating the same notification maintains the same balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // A new notification adds a new balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(2u, notifications_->notifications().size());
  EXPECT_TRUE(FindNotification("DFpath"));
  EXPECT_TRUE(FindNotification("Dpath"));
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Hiding a notification removes it from our data.
  notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(1u, notifications_->notifications().size());
  EXPECT_FALSE(FindNotification("DFpath"));
  EXPECT_TRUE(FindNotification("Dpath"));

  // Balloons don't go away until we run the message loop.
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Running the message loop allows the balloon to disappear.
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_FALSE(FindBalloon("DFpath"));
  EXPECT_TRUE(FindBalloon("Dpath"));
};

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_ShowDelayedTest DISABLED_ShowDelayedTest
#else
// TODO(jamescook): This test is flaky on linux_chromeos, occasionally causing
// this assertion failure inside Gtk:
//   "murrine_style_draw_box: assertion `height >= -1' failed"
// There may be an underlying bug in the ChromeOS notification code.
// I'm not marking it as FLAKY because this doesn't happen on the bots.
#define MAYBE_ShowDelayedTest ShowDelayedTest
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_ShowDelayedTest) {
  InitNotifications();
  // Adding a delayed notification does not show a balloon.
  notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE,
                                          "path", 3000);
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Forcing the show to happen makes the balloon appear.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Showing a notification both immediately and delayed results in one
  // additional balloon.
  notifications_->ShowNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL,
                                          "path", 3000);
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));

  // When the delayed notification arrives, it's an update, so we still only
  // have two balloons.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));

  // If we schedule a show for later, then hide before it becomes visible,
  // the balloon should not be added.
  notifications_->ShowNotificationDelayed(
      FileBrowserNotifications::FORMAT_FAIL, "path", 3000);
  notifications_->HideNotification(FileBrowserNotifications::FORMAT_FAIL,
                                   "path");
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_FALSE(FindBalloon("Fpath"));

  // Even when we try to force the show, nothing appears, because the balloon
  // was explicitly hidden.
  notifications_->ExecuteShow();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(2u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));
  EXPECT_TRUE(FindBalloon("DFpath"));
  EXPECT_FALSE(FindBalloon("Fpath"));
}

#if defined(USE_AURA)
// TODO(jamescook): Fails on linux_chromeos_aura because we haven't implemented
// chromeos::SystemNotification yet.  http://crbug.com/104471
#define MAYBE_HideDelayedTest DISABLED_HideDelayedTest
#else
#define MAYBE_HideDelayedTest HideDelayedTest
#endif
IN_PROC_BROWSER_TEST_F(FileBrowserNotificationsTest, MAYBE_HideDelayedTest) {
  InitNotifications();
  // Showing now, and scheduling a hide for later, results in one balloon.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE, "path");
  notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE,
                                          "path", 3000);
  EXPECT_EQ(1u, collection_->GetActiveBalloons().size());
  EXPECT_TRUE(FindBalloon("Dpath"));

  // Forcing the hide removes the balloon.
  notifications_->ExecuteHide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Immediate show then hide results in no balloons.
  notifications_->ShowNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  notifications_->HideNotification(FileBrowserNotifications::DEVICE_FAIL,
                                   "path");
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());

  // Delayed hide for a notification that doesn't exist does nothing.
  notifications_->HideNotificationDelayed(FileBrowserNotifications::DEVICE_FAIL,
                                          "path", 3000);
  notifications_->ExecuteHide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_EQ(0u, collection_->GetActiveBalloons().size());
}

}  // namespace chromeos.
<|endoftext|>


<commit_before>#include "AppDelegate.h"
#include "HelloWorldScene.h"

USING_NS_CC;
USING_NS_CC_DEN;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate() {
}

void AppDelegate::initGLContextAttrs() {
    //set OpenGL context attributions,now can only set six attributions:
    //red,green,blue,alpha,depth,stencil
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};

    GLView::setGLContextAttrs(glContextAttrs);
}

void AppDelegate::initSoundAndMusic() {
    //initialize bgm
    SimpleAudioEngine::getInstance()->preloadBackgroundMusic(FILE_BGM);
    UserDefault::getInstance()->setBoolForKey(MUSIC_KEY, true);
    UserDefault::getInstance()->setBoolForKey(MUSIC_PLAYED_KEY, false);

    //initialize effect
    SimpleAudioEngine::getInstance()->preloadEffect(FILE_SOUND_1);
    UserDefault::getInstance()->setBoolForKey(SOUND_KEY, true);
}

bool AppDelegate::applicationDidFinishLaunching() {
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();

    if (!glview) {
        glview = GLViewImpl::createWithRect("PHOTON", Rect(0, 0, WINDOW_SIZE));
        director->setOpenGLView(glview);
    }

    director->getOpenGLView()->setDesignResolutionSize(WINDOW_SIZE, ResolutionPolicy::SHOW_ALL);

    director->setDisplayStats(true);

    director->setAnimationInterval(1.0 / 60);

    FileUtils::getInstance()->addSearchPath("res");

    this->initSoundAndMusic();

    auto scene = HelloWorld::createScene();

    director->runWithScene(scene);

    return true;
}

void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

    SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}

void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();
    if (UserDefault::getInstance()->getBoolForKey(MUSIC_KEY)) {
        SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
    }
}

<commit_msg>Delete AppDelegate.cpp<commit_after><|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param path the original path
     * @return the simplified path
     */
    string simplifyPath(string& path) {
        vector<string> names;
        vector<string> tokens(move(split(path, '/')));
        for (const auto& token : tokens) {
            if (token == ".." && !names.empty()) {
                names.pop_back();
            } else if (token != ".." && token != "." && !token.empty()) {
                names.emplace_back(token);
            }
        }
        return string("/").append(move(join(names, '/')));
    }

    // Split string by delimitor.
    vector<string> split(const string& s, const char delim) {
        vector<string> tokens;
        stringstream ss(s);
        string token;
        while (getline(ss, token, delim)) {
            tokens.emplace_back(token);
        }
        return tokens;
    }

    // Join strings with delimitor.
    string join(const vector<string>& names, const char& delim) {
        string s;
        if (!names.empty()) {
            ostringstream ss;
            string delim_str;
            delim_str.insert(delim_str.begin(), delim);
            copy(names.cbegin(), prev(names.cend()),
                 ostream_iterator<string>(ss, delim_str.c_str()));
            ss << names.back();
            s = ss.str();
        }
        return s;
    }
};
<commit_msg>Update simplify-path.cpp<commit_after>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    /**
     * @param path the original path
     * @return the simplified path
     */
    string simplifyPath(string& path) {
        vector<string> names;
        vector<string> tokens(move(split(path, '/')));
        for (const auto& token : tokens) {
            if (token == ".." && !names.empty()) {
                names.pop_back();
            } else if (token != ".." && token != "." && !token.empty()) {
                names.emplace_back(token);
            }
        }
        return string("/").append(join(names, '/'));
    }

    // Split string by delimitor.
    vector<string> split(const string& s, const char delim) {
        vector<string> tokens;
        stringstream ss(s);
        string token;
        while (getline(ss, token, delim)) {
            tokens.emplace_back(token);
        }
        return tokens;
    }

    // Join strings with delimitor.
    string join(const vector<string>& names, const char& delim) {
        string s;
        if (!names.empty()) {
            ostringstream ss;
            string delim_str;
            delim_str.insert(delim_str.begin(), delim);
            copy(names.cbegin(), prev(names.cend()),
                 ostream_iterator<string>(ss, delim_str.c_str()));
            ss << names.back();
            s = ss.str();
        }
        return s;
    }
};
<|endoftext|>


<commit_before>/*
 * GameScene.cpp
 *
 *  Created on: Sep 16, 2014
 *      Author: zhangchen
 */

#include "GameScene.h"
#include "BgLayer.h"
#include "EffectUtils.h"
#include "Menu.h"
#include "FinishScene.h"

#define TAG_LAYER_GAME 0
#define TAG_LAYER_PAUSE 1
#define TAG_SCORE 3
#define TAG_LAYER_HELP 4

GameLayer::GameLayer() :
		running(true) {
	timer = TimerSprite::create();
	CC_SAFE_RETAIN(timer);
}

GameLayer::~GameLayer() {
	CC_SAFE_RELEASE(timer);
}

bool GameLayer::init() {
	if (CCLayer::init()) {
		LOCAL_CONTEXT->clearScore();

		this->setTouchMode(kCCTouchesOneByOne);
		this->setTouchEnabled(true);
		this->scheduleUpdate();
		CCSize s = CCDirector::sharedDirector()->getWinSize();
		this->ignoreAnchorPointForPosition(true);
		setAnchorPoint(ccp(0.5f, 0.5f));
		this->setContentSize(s);
		setPosition(ccp(s.width / 2, s.height / 2));

		/*-- 计分 --*/
		CCLabelTTF *score = CCLabelTTF::create(CCString::createWithFormat("%d", LOCAL_CONTEXT->getScore())->getCString(),LOCAL_RESOURCES->valueByKey("font")->getCString(),LOCAL_RESOURCES->valueByKey("font_size")->floatValue());
		score->setColor(LOCAL_CONTEXT->getFontColor());
		score->setAnchorPoint(ccp(1, 1));
		score->setPosition(ccpp(0.5,0.5));
		this->addChild(score,0,TAG_SCORE);

		/*-- 倒计时 --*/
		CCSprite *timeBack = CCSprite::create("time_back.png");
		timeBack->setAnchorPoint(ccp(0.5,0.5));
		timeBack->setPosition(ccpp(0,0.32));
		this->addChild(timeBack);
		timer->setAnchorPoint(ccp(0.5,0.5));
		timer->setPosition(ccp(timeBack->getContentSize().width/2,timeBack->getContentSize().height/2));
		timer->setTarget(this,callfunc_selector(GameLayer::gameover));
		timeBack->addChild(timer);

		/*-- 放瓶子 --*/
		initPosition();

		if (LOCAL_CONTEXT->isFirstRun()) {
			this->createHelpLayer();
		} else {
			timer->start();
		}
		return true;

	} else {
		return false;
	}
}

CCScene * GameLayer::scene() {
	CCScene *scene = CCScene::create();
	if (scene && scene->init()) {
		if (scene) {
			/*-- 背景 --*/
			scene->addChild(BgLayer::create());
			GameLayer *layer = GameLayer::create();
			scene->addChild(layer, TAG_LAYER_GAME);
			scene->addChild(layer->createPauseButtonLayer());
		}
		return scene;
	} else {
		CC_SAFE_DELETE(scene);
		return NULL;
	}

}

void GameLayer::correct(float offset) {
	CCSprite *lastItem = items[0];
	CCSprite *lastBlock = blocks[0];
	LOCAL_CONTEXT->increaseScore();
	((CCLabelTTF*) this->getChildByTag(TAG_SCORE))->setString(
			CCString::createWithFormat("%d", LOCAL_CONTEXT->getScore())->getCString());
	moveForward();
	lastItem->runAction(
			CCSequence::create(CCMoveBy::create(0.3, ccpp(offset, 0)),
					CCFadeOut::create(0.3),
					CCCallFunc::create(lastItem,
							callfunc_selector(CCSprite::removeFromParent)),
					CCCallFunc::create(this,
							callfunc_selector(GameLayer::enable)),
					NULL));
	lastBlock->runAction(
			CCSequence::createWithTwoActions(
					CCMoveTo::create(0.3, ccpp(0, -0.5)),
					CCCallFunc::create(lastBlock,
							callfunc_selector(CCSprite::removeFromParent))));
	timer->reset();
}

void GameLayer::mistake(float offset) {
	CCSprite *lastItem = items[0];
	CCSprite *wrong = CCSprite::create("bg_wrong.png");
	wrong->setAnchorPoint(ccp(0.5, 0));
	wrong->setPosition(lastItem->getPosition() + ccpp(offset, 0));
	this->addChild(wrong);
	lastItem->runAction(
			CCSequence::createWithTwoActions(
					CCMoveBy::create(0.6, ccpp(offset, 0)),
					CCCallFunc::create(this,
							callfunc_selector(GameLayer::gameover))));
}

bool GameLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
	if (LOCAL_CONTEXT->firstRun()) { //第一次启动，点击取消帮助画面层
		this->removeHelpLayer();
		return false;
	}

	if (running) {
		disable();
		CCSprite *lastItem = items[0];
		long itemnum = (long) lastItem->getUserData();
		//CCDirector::sharedDirector()->replaceScene(FinishLayer::scene());
		CCSize winsize = CCDirector::sharedDirector()->getWinSize();
		CCPoint location = pTouch->getLocation();
		if (location.x < winsize.width / 2) {
			//瓶子 6-10
			if (itemnum >= 6) {
				correct(-0.32);
			} else {
				mistake(-0.32);
			}
		} else {
			//罐子 1-5
			if (itemnum <= 5) {
				correct(0.32);
			} else {
				mistake(0.32);
			}
		}
		return true;
	} else {
		return false;
	}
}

void GameLayer::onPauseItem(CCObject *object) {
	if (running) {
		disable();
		timer->pause();
		effect::clickButton((CCMenuItem*) object);
		createPauseLayer();
	}
}

void GameLayer::resume() {
	CCDirector::sharedDirector()->getRunningScene()->removeChildByTag(
	TAG_LAYER_PAUSE);
	timer->resume();
	enable();
}

void GameLayer::onResumeItem(CCObject *object) {
	if (!running) {
		effect::clickButton((CCMenuItem*) object, this,
				callfunc_selector(GameLayer::resume));
	}
}

void GameLayer::backMenu() {
	CCDirector::sharedDirector()->replaceScene(MenuLayer::scene());
}

void GameLayer::onBackItem(CCObject *object) {
	effect::clickButton((CCMenuItem*) object, this,
			callfunc_selector(GameLayer::backMenu));
}

CCLayer * GameLayer::createPauseButtonLayer() {
	CCMenu *layer = CCMenu::create();
	//暂停
	CCMenuItemImage *pausebg = CCMenuItemImage::create(("btn_small.png"),
			("btn_small.png"));
	CCSprite *pausetxt = CCSprite::create("btn_pause.png");
	pausebg->setTarget(this, menu_selector(GameLayer::onPauseItem));
	pausebg->setAnchorPoint(ccp(0, 1));
	pausebg->setPosition(ccpp(-0.49, 0.49));
	pausetxt->setPosition(
			ccp(pausebg->getContentSize().width / 2,
					pausebg->getContentSize().height / 2));
	pausetxt->setAnchorPoint(ccp(0.5, 0.5));
	pausebg->addChild(pausetxt);
	layer->addChild(pausebg);
	return layer;
}

void GameLayer::createHelpLayer() {
	CCLayer *layer = CCLayer::create();
	CCSprite *left = CCSprite::create("help_left.png");
	left->setAnchorPoint(ccp(0.5, 0));
	left->setPosition(ccpp(-0.33, -0.345));
	CCSprite *right = CCSprite::create("help_right.png");
	right->setAnchorPoint(ccp(0.5, 0));
	right->setPosition(ccpp(0.33, -0.345));
	layer->addChild(left);
	layer->addChild(right);
	this->addChild(layer, 0, TAG_LAYER_HELP);
}

void GameLayer::removeHelpLayer() {
	this->removeChildByTag(TAG_LAYER_HELP);
	timer->start();
}

void GameLayer::createPauseLayer() {
	Context *context = Context::sharedContext();
	CCSize s = CCDirector::sharedDirector()->getWinSize();
	/* 半透明层 */
	CCLayerColor* pauseLayer = CCLayerColor::create();
	pauseLayer->setContentSize(CCSizeMake(s.width, s.height));
	pauseLayer->setColor(ccc3(0, 0, 0));
	pauseLayer->setOpacity(150);
	CCMenu *menu = CCMenu::create();
//回到游戏
	CCMenuItemImage *resumebg = CCMenuItemImage::create(("btn_big.png"),
			("btn_big.png"));
	resumebg->setTarget(this, menu_selector(GameLayer::onResumeItem));
	CCMenuItemFont *resumetxt = CCMenuItemFont::create(LOCAL_RESOURCES->valueByKey("i18n_resume")->getCString());
	resumebg->setAnchorPoint(ccp(0.5, 0.5));
	resumebg->setPosition(ccpp(0, 0));
	resumetxt->setPosition(
			ccp(resumebg->getContentSize().width / 2,
					resumebg->getContentSize().height / 2));
	resumetxt->setAnchorPoint(ccp(0.5, 0.5));
	resumetxt->setColor(context->getFontColor());
	resumebg->addChild(resumetxt);
	menu->addChild(resumebg);

//回到菜单
	CCMenuItemImage *backbg = CCMenuItemImage::create(("btn_big.png"),
			("btn_big.png"));
	backbg->setTarget(this, menu_selector(GameLayer::onBackItem));
	CCMenuItemFont *backtxt = CCMenuItemFont::create(LOCAL_RESOURCES->valueByKey("i18n_back")->getCString());
	backbg->setAnchorPoint(ccp(0.5, 0.5));
	backbg->setPosition(ccpp(0, -0.12));
	backtxt->setPosition(
			ccp(backbg->getContentSize().width / 2,
					backbg->getContentSize().height / 2));
	backtxt->setAnchorPoint(ccp(0.5, 0.5));
	backtxt->setColor(context->getFontColor());
	backbg->addChild(backtxt);
	menu->addChild(backbg);

	pauseLayer->addChild(menu);
	CCDirector::sharedDirector()->getRunningScene()->addChild(pauseLayer, 0,
	TAG_LAYER_PAUSE);
}

void GameLayer::moveForward() {
	disable();
	items[ITEM_NUM] = createNewItem();
	blocks[ITEM_NUM] = createNewBlock();
	items[ITEM_NUM]->setPosition(items[ITEM_NUM - 1]->getPosition());
	blocks[ITEM_NUM]->setPosition(blocks[ITEM_NUM - 1]->getPosition());

	/* 向下移动的动画 */
	for (unsigned int i = ITEM_NUM - 1; i > 0; i--) {
		items[i]->runAction(
				CCMoveTo::create(0.3f, items[i - 1]->getPosition()));
		blocks[i]->runAction(
				CCMoveTo::create(0.3f, blocks[i - 1]->getPosition()));
	}
	/* 重新设置数组存储顺序和前后遮挡排列顺序 */
	for (unsigned int i = 0; i < ITEM_NUM; i++) {
		items[i] = items[i + 1];
		items[i]->setZOrder(ITEM_NUM - i);

		blocks[i] = blocks[i + 1];
		blocks[i]->setZOrder(ITEM_NUM - i);
	}
}

void GameLayer::initPosition() {
	for (unsigned int i = 0; i < ITEM_NUM; i++) {
		items[i] = createNewItem();
		items[i]->setZOrder(ITEM_NUM - i);
		items[i]->setPosition(ccpp(0, (-0.38 + 0.11 * i)));

		blocks[i] = createNewBlock();
		blocks[i]->setZOrder(ITEM_NUM - i);
		blocks[i]->setPosition(items[i]->getPosition() + ccpp(0, -0.02));
	}
}

CCSprite* GameLayer::createNewItem() {
	long i = rand() % 10 + 1;
	CCString *s = CCString::createWithFormat("item_%ld.png", i);
	CCSprite* itemnew = CCSprite::create(s->getCString());
	itemnew->setUserData((void *) i);
	itemnew->setAnchorPoint(ccp(0.5, 0));
	itemnew->runAction(CCFadeIn::create(1.0f));
	this->addChild(itemnew);
	return itemnew;
}

CCSprite* GameLayer::createNewBlock() {
	CCSprite *block = CCSprite::create("bg_block.png");
	block->setAnchorPoint(ccp(0.5, 0));
	this->addChild(block);
	return block;
}

void GameLayer::disable() {
	this->running = false;
	timer->pause();
}

void GameLayer::enable() {
	this->running = true;
	timer->resume();
}

void GameLayer::gameover() {
	LOCAL_CONTEXT->save();
	CCDirector::sharedDirector()->replaceScene(CCTransitionFadeDown::create(0.5f, FinishLayer::scene()));
}

/*-- 计时器 --*/
TimerSprite::TimerSprite() {
	initTimer();
}

TimerSprite::~TimerSprite() {
}

bool TimerSprite::init() {
	if (TimerSprite::initWithSprite(CCSprite::create("time_front.png"))) {
		this->setType(kCCProgressTimerTypeBar);
		this->setMidpoint(ccp(0, 0));
		this->setBarChangeRate(ccp(1, 0));
		return true;
	} else {
		return false;
	}
}

void TimerSprite::initTimer() {
	int score = LOCAL_CONTEXT->getScore();
	if (score <= 30) {
		this->time = 5;
	} else if (score <= 60) {
		this->time = 4;
	} else if (score <= 100) {
		this->time = 3;
	} else {
		this->time = 2;
	}
}

void TimerSprite::reset() {
	this->stopAllActions();
	initTimer();
	this->runAction(
			CCSequence::createWithTwoActions(
					CCProgressFromTo::create(time, 100.0f, 0.0f),
					CCCallFunc::create(this,
							callfunc_selector(TimerSprite::timeout))));
}

void TimerSprite::start() {
	reset();
}

void TimerSprite::resume() {
	this->resumeSchedulerAndActions();
}

void TimerSprite::pause() {
	this->pauseSchedulerAndActions();
}

void TimerSprite::timeout() {
	if (m_listener && m_callfunc) {
		(m_listener->*m_callfunc)();
	}
}

void TimerSprite::setTarget(CCObject * target, SEL_CallFunc function) {
	this->m_listener = target;
	this->m_callfunc = function;
}
<commit_msg>adjust interval<commit_after>/*
 * GameScene.cpp
 *
 *  Created on: Sep 16, 2014
 *      Author: zhangchen
 */

#include "GameScene.h"
#include "BgLayer.h"
#include "EffectUtils.h"
#include "Menu.h"
#include "FinishScene.h"

#define TAG_LAYER_GAME 0
#define TAG_LAYER_PAUSE 1
#define TAG_SCORE 3
#define TAG_LAYER_HELP 4

GameLayer::GameLayer() :
		running(true) {
	timer = TimerSprite::create();
	CC_SAFE_RETAIN(timer);
}

GameLayer::~GameLayer() {
	CC_SAFE_RELEASE(timer);
}

bool GameLayer::init() {
	if (CCLayer::init()) {
		LOCAL_CONTEXT->clearScore();

		this->setTouchMode(kCCTouchesOneByOne);
		this->setTouchEnabled(true);
		this->scheduleUpdate();
		CCSize s = CCDirector::sharedDirector()->getWinSize();
		this->ignoreAnchorPointForPosition(true);
		setAnchorPoint(ccp(0.5f, 0.5f));
		this->setContentSize(s);
		setPosition(ccp(s.width / 2, s.height / 2));

		/*-- 计分 --*/
		CCLabelTTF *score = CCLabelTTF::create(CCString::createWithFormat("%d", LOCAL_CONTEXT->getScore())->getCString(),LOCAL_RESOURCES->valueByKey("font")->getCString(),LOCAL_RESOURCES->valueByKey("font_size")->floatValue());
		score->setColor(LOCAL_CONTEXT->getFontColor());
		score->setAnchorPoint(ccp(1, 1));
		score->setPosition(ccpp(0.5,0.5));
		this->addChild(score,0,TAG_SCORE);

		/*-- 倒计时 --*/
		CCSprite *timeBack = CCSprite::create("time_back.png");
		timeBack->setAnchorPoint(ccp(0.5,0.5));
		timeBack->setPosition(ccpp(0,0.32));
		this->addChild(timeBack);
		timer->setAnchorPoint(ccp(0.5,0.5));
		timer->setPosition(ccp(timeBack->getContentSize().width/2,timeBack->getContentSize().height/2));
		timer->setTarget(this,callfunc_selector(GameLayer::gameover));
		timeBack->addChild(timer);

		/*-- 放瓶子 --*/
		initPosition();

		if (LOCAL_CONTEXT->isFirstRun()) {
			this->createHelpLayer();
		} else {
			timer->start();
		}
		return true;

	} else {
		return false;
	}
}

CCScene * GameLayer::scene() {
	CCScene *scene = CCScene::create();
	if (scene && scene->init()) {
		if (scene) {
			/*-- 背景 --*/
			scene->addChild(BgLayer::create());
			GameLayer *layer = GameLayer::create();
			scene->addChild(layer, TAG_LAYER_GAME);
			scene->addChild(layer->createPauseButtonLayer());
		}
		return scene;
	} else {
		CC_SAFE_DELETE(scene);
		return NULL;
	}

}

void GameLayer::correct(float offset) {
	CCSprite *lastItem = items[0];
	CCSprite *lastBlock = blocks[0];
	LOCAL_CONTEXT->increaseScore();
	((CCLabelTTF*) this->getChildByTag(TAG_SCORE))->setString(
			CCString::createWithFormat("%d", LOCAL_CONTEXT->getScore())->getCString());
	moveForward();
	lastItem->runAction(
			CCSequence::create(CCMoveBy::create(0.3, ccpp(offset, 0)),
					CCFadeOut::create(0.3),
					CCCallFunc::create(lastItem,
							callfunc_selector(CCSprite::removeFromParent)),
					NULL));
	lastBlock->runAction(
			CCSequence::createWithTwoActions(
					CCMoveTo::create(0.3, ccpp(0, -0.5)),
					CCCallFunc::create(lastBlock,
							callfunc_selector(CCSprite::removeFromParent))));
	timer->reset();
}

void GameLayer::mistake(float offset) {
	CCSprite *lastItem = items[0];
	CCSprite *wrong = CCSprite::create("bg_wrong.png");
	wrong->setAnchorPoint(ccp(0.5, 0));
	wrong->setPosition(lastItem->getPosition() + ccpp(offset, 0));
	this->addChild(wrong);
	lastItem->runAction(
			CCSequence::createWithTwoActions(
					CCMoveBy::create(0.6, ccpp(offset, 0)),
					CCCallFunc::create(this,
							callfunc_selector(GameLayer::gameover))));
}

bool GameLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
	if (LOCAL_CONTEXT->firstRun()) { //第一次启动，点击取消帮助画面层
		this->removeHelpLayer();
		return false;
	}

	if (running) {
		disable();
		CCSprite *lastItem = items[0];
		long itemnum = (long) lastItem->getUserData();
		//CCDirector::sharedDirector()->replaceScene(FinishLayer::scene());
		CCSize winsize = CCDirector::sharedDirector()->getWinSize();
		CCPoint location = pTouch->getLocation();
		if (location.x < winsize.width / 2) {
			//瓶子 6-10
			if (itemnum >= 6) {
				correct(-0.32);
			} else {
				mistake(-0.32);
			}
		} else {
			//罐子 1-5
			if (itemnum <= 5) {
				correct(0.32);
			} else {
				mistake(0.32);
			}
		}
		return true;
	} else {
		return false;
	}
}

void GameLayer::onPauseItem(CCObject *object) {
	if (running) {
		disable();
		timer->pause();
		effect::clickButton((CCMenuItem*) object);
		createPauseLayer();
	}
}

void GameLayer::resume() {
	CCDirector::sharedDirector()->getRunningScene()->removeChildByTag(
	TAG_LAYER_PAUSE);
	timer->resume();
	enable();
}

void GameLayer::onResumeItem(CCObject *object) {
	if (!running) {
		effect::clickButton((CCMenuItem*) object, this,
				callfunc_selector(GameLayer::resume));
	}
}

void GameLayer::backMenu() {
	CCDirector::sharedDirector()->replaceScene(MenuLayer::scene());
}

void GameLayer::onBackItem(CCObject *object) {
	effect::clickButton((CCMenuItem*) object, this,
			callfunc_selector(GameLayer::backMenu));
}

CCLayer * GameLayer::createPauseButtonLayer() {
	CCMenu *layer = CCMenu::create();
	//暂停
	CCMenuItemImage *pausebg = CCMenuItemImage::create(("btn_small.png"),
			("btn_small.png"));
	CCSprite *pausetxt = CCSprite::create("btn_pause.png");
	pausebg->setTarget(this, menu_selector(GameLayer::onPauseItem));
	pausebg->setAnchorPoint(ccp(0, 1));
	pausebg->setPosition(ccpp(-0.49, 0.49));
	pausetxt->setPosition(
			ccp(pausebg->getContentSize().width / 2,
					pausebg->getContentSize().height / 2));
	pausetxt->setAnchorPoint(ccp(0.5, 0.5));
	pausebg->addChild(pausetxt);
	layer->addChild(pausebg);
	return layer;
}

void GameLayer::createHelpLayer() {
	CCLayer *layer = CCLayer::create();
	CCSprite *left = CCSprite::create("help_left.png");
	left->setAnchorPoint(ccp(0.5, 0));
	left->setPosition(ccpp(-0.33, -0.345));
	CCSprite *right = CCSprite::create("help_right.png");
	right->setAnchorPoint(ccp(0.5, 0));
	right->setPosition(ccpp(0.33, -0.345));
	layer->addChild(left);
	layer->addChild(right);
	this->addChild(layer, 0, TAG_LAYER_HELP);
}

void GameLayer::removeHelpLayer() {
	this->removeChildByTag(TAG_LAYER_HELP);
	timer->start();
}

void GameLayer::createPauseLayer() {
	Context *context = Context::sharedContext();
	CCSize s = CCDirector::sharedDirector()->getWinSize();
	/* 半透明层 */
	CCLayerColor* pauseLayer = CCLayerColor::create();
	pauseLayer->setContentSize(CCSizeMake(s.width, s.height));
	pauseLayer->setColor(ccc3(0, 0, 0));
	pauseLayer->setOpacity(150);
	CCMenu *menu = CCMenu::create();
//回到游戏
	CCMenuItemImage *resumebg = CCMenuItemImage::create(("btn_big.png"),
			("btn_big.png"));
	resumebg->setTarget(this, menu_selector(GameLayer::onResumeItem));
	CCMenuItemFont *resumetxt = CCMenuItemFont::create(LOCAL_RESOURCES->valueByKey("i18n_resume")->getCString());
	resumebg->setAnchorPoint(ccp(0.5, 0.5));
	resumebg->setPosition(ccpp(0, 0));
	resumetxt->setPosition(
			ccp(resumebg->getContentSize().width / 2,
					resumebg->getContentSize().height / 2));
	resumetxt->setAnchorPoint(ccp(0.5, 0.5));
	resumetxt->setColor(context->getFontColor());
	resumebg->addChild(resumetxt);
	menu->addChild(resumebg);

//回到菜单
	CCMenuItemImage *backbg = CCMenuItemImage::create(("btn_big.png"),
			("btn_big.png"));
	backbg->setTarget(this, menu_selector(GameLayer::onBackItem));
	CCMenuItemFont *backtxt = CCMenuItemFont::create(LOCAL_RESOURCES->valueByKey("i18n_back")->getCString());
	backbg->setAnchorPoint(ccp(0.5, 0.5));
	backbg->setPosition(ccpp(0, -0.12));
	backtxt->setPosition(
			ccp(backbg->getContentSize().width / 2,
					backbg->getContentSize().height / 2));
	backtxt->setAnchorPoint(ccp(0.5, 0.5));
	backtxt->setColor(context->getFontColor());
	backbg->addChild(backtxt);
	menu->addChild(backbg);

	pauseLayer->addChild(menu);
	CCDirector::sharedDirector()->getRunningScene()->addChild(pauseLayer, 0,
	TAG_LAYER_PAUSE);
}

void GameLayer::moveForward() {
	disable();
	items[ITEM_NUM] = createNewItem();
	blocks[ITEM_NUM] = createNewBlock();
	items[ITEM_NUM]->setPosition(items[ITEM_NUM - 1]->getPosition());
	blocks[ITEM_NUM]->setPosition(blocks[ITEM_NUM - 1]->getPosition());
	/* 向下移动的动画 */
	for (unsigned int i = ITEM_NUM - 1; i > 0; i--) {
		items[i]->runAction(
				CCSequence::createWithTwoActions(
						CCMoveTo::create(0.1f, items[i - 1]->getPosition()),
						CCCallFunc::create(this,
								callfunc_selector(GameLayer::enable))));
		blocks[i]->runAction(
				CCMoveTo::create(0.1f, blocks[i - 1]->getPosition()));
	}
	/* 重新设置数组存储顺序和前后遮挡排列顺序 */
	for (unsigned int i = 0; i < ITEM_NUM; i++) {
		items[i] = items[i + 1];
		items[i]->setZOrder(ITEM_NUM - i);

		blocks[i] = blocks[i + 1];
		blocks[i]->setZOrder(ITEM_NUM - i);
	}
}

void GameLayer::initPosition() {
	for (unsigned int i = 0; i < ITEM_NUM; i++) {
		items[i] = createNewItem();
		items[i]->setZOrder(ITEM_NUM - i);
		items[i]->setPosition(ccpp(0, (-0.38 + 0.11 * i)));

		blocks[i] = createNewBlock();
		blocks[i]->setZOrder(ITEM_NUM - i);
		blocks[i]->setPosition(items[i]->getPosition() + ccpp(0, -0.02));
	}
}

CCSprite* GameLayer::createNewItem() {
	long i = rand() % 10 + 1;
	CCString *s = CCString::createWithFormat("item_%ld.png", i);
	CCSprite* itemnew = CCSprite::create(s->getCString());
	itemnew->setUserData((void *) i);
	itemnew->setAnchorPoint(ccp(0.5, 0));
	itemnew->runAction(CCFadeIn::create(1.0f));
	this->addChild(itemnew);
	return itemnew;
}

CCSprite* GameLayer::createNewBlock() {
	CCSprite *block = CCSprite::create("bg_block.png");
	block->setAnchorPoint(ccp(0.5, 0));
	this->addChild(block);
	return block;
}

void GameLayer::disable() {
	this->running = false;
	timer->pause();
}

void GameLayer::enable() {
	this->running = true;
	timer->resume();
}

void GameLayer::gameover() {
	LOCAL_CONTEXT->save();
	CCDirector::sharedDirector()->replaceScene(CCTransitionFadeDown::create(0.5f, FinishLayer::scene()));
}

/*-- 计时器 --*/
TimerSprite::TimerSprite() {
	initTimer();
}

TimerSprite::~TimerSprite() {
}

bool TimerSprite::init() {
	if (TimerSprite::initWithSprite(CCSprite::create("time_front.png"))) {
		this->setType(kCCProgressTimerTypeBar);
		this->setMidpoint(ccp(0, 0));
		this->setBarChangeRate(ccp(1, 0));
		return true;
	} else {
		return false;
	}
}

void TimerSprite::initTimer() {
	int score = LOCAL_CONTEXT->getScore();
	if (score <= 30) {
		this->time = 5;
	} else if (score <= 60) {
		this->time = 4;
	} else if (score <= 100) {
		this->time = 3;
	} else {
		this->time = 2;
	}
}

void TimerSprite::reset() {
	this->stopAllActions();
	initTimer();
	this->runAction(
			CCSequence::createWithTwoActions(
					CCProgressFromTo::create(time, 100.0f, 0.0f),
					CCCallFunc::create(this,
							callfunc_selector(TimerSprite::timeout))));
}

void TimerSprite::start() {
	reset();
}

void TimerSprite::resume() {
	this->resumeSchedulerAndActions();
}

void TimerSprite::pause() {
	this->pauseSchedulerAndActions();
}

void TimerSprite::timeout() {
	if (m_listener && m_callfunc) {
		(m_listener->*m_callfunc)();
	}
}

void TimerSprite::setTarget(CCObject * target, SEL_CallFunc function) {
	this->m_listener = target;
	this->m_callfunc = function;
}
<|endoftext|>