<commit_before>//
//  MenuItemViews.m
//  slide_menu
//
//  Created by <NAME> on 1/7/13.
//  Copyright (c) 2013 <NAME>. All rights reserved.
//

#import <cassert>

#import <QuartzCore/QuartzCore.h>

#import "MenuViewController.h"
#import "MenuItemViews.h"
#import "GUIHelpers.h"

//Menu GUI constants.
//It's a C++, all these constants have
//internal linkage without any 'static',
//and no need for unnamed namespace.
const CGFloat groupMenuItemFontSize = 18.f;
const CGFloat childMenuItemFontSize = 14.f;
NSString * const menuFontName = @"PT Sans";
const CGSize menuTextShadowOffset = CGSizeMake(2.f, 2.f);
const CGFloat menuTextShadowAlpha = 0.5f;
const CGFloat menuItemImageSize = 24.f;//must be square image.
const CGFloat groupMenuItemTextIdent = 10.f;
const CGFloat groupMenuItemTextHeight = 20.f;
const CGFloat childMenuItemTextIdent = 20.f;
const CGFloat childMenuItemTextHeight = 20.f;
const CGFloat discloseTriangleSize = 14.f;
const CGFloat groupMenuItemLeftMargin = 80.f;

using CernAPP::ItemStyle;

@implementation MenuItemView {
   ItemStyle itemStyle;

   //Weak, we do not have to control life time of these objects.
   __weak NSObject<MenuItemProtocol> *menuItem;
   __weak MenuViewController *controller;

   UILabel *itemLabel;
}

@synthesize isSelected;

//________________________________________________________________________________________
- (id) initWithFrame : (CGRect) frame item : (NSObject<MenuItemProtocol> *) anItem
       style : (CernAPP::ItemStyle) aStyle controller : (MenuViewController *) aController
{
   assert(aStyle == ItemStyle::standalone || aStyle == ItemStyle::separator || aStyle == ItemStyle::child &&
          "initWithFrame:item:style:controller:, parameter 'aStyle' is invalid");
   assert(aStyle == ItemStyle::separator || anItem &&
          "initWithFrame:item:style:controller:, parameter 'anItem' is nil and style is not a separator");
   assert(aController != nil && "initWithFrame:item:style:controller:, parameter 'aController' is nil");

   if (self = [super initWithFrame : frame]) {
      menuItem = anItem;
      itemStyle = aStyle;
      controller = aController;
      
      if (aStyle != ItemStyle::separator) {//Separator is simply a blank row in a menu.
         UITapGestureRecognizer * const tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector(handleTap)];
         [tapRecognizer setNumberOfTapsRequired : 1];
         [self addGestureRecognizer : tapRecognizer];
         
         itemLabel = [[UILabel alloc] initWithFrame : CGRect()];
         itemLabel.text = menuItem.itemText;

         UIFont * const font = [UIFont fontWithName : menuFontName size : childMenuItemFontSize];
         assert(font != nil && "initWithFrame:item:style:controller:, font not found");
         itemLabel.font = font;
      
         itemLabel.textAlignment = NSTextAlignmentLeft;
         itemLabel.numberOfLines = 1;
         itemLabel.clipsToBounds = YES;
         itemLabel.backgroundColor = [UIColor clearColor];

         [self addSubview : itemLabel];
      }
      
      isSelected = NO;
   }
   
   return self;
}

//________________________________________________________________________________________
- (void) fill : (CGRect) rect withContext : (CGContextRef) ctx withGradient : (const CGFloat *) gradientColor
{
   assert(ctx != nullptr && "fill:withContext:withGradient:, parameter 'ctx' is null");
   assert(gradientColor != nullptr && "fill:withContext:withGradient:, parameter 'gradientColor' is null");

   CGPoint startPoint = CGPointZero;
   CGPoint endPoint = CGPointMake(0.f, rect.size.height);
      
   //Create a gradient.
   CGColorSpaceRef baseSpace(CGColorSpaceCreateDeviceRGB());
   CGFloat positions[] = {0.f, 1.f};
   //      CGFloat colors[][4] = {{0.f, 0.564f, 0.949f, 1.f}, {0.f, 0.431f, .901, 1.f}};

   CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, gradientColor, positions, 2);
   CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 0);
      
   CGGradientRelease(gradient);
   CGColorSpaceRelease(baseSpace);
}

//________________________________________________________________________________________
- (void) drawRect : (CGRect) rect
{
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   
   //For a separator - simply fill a rectangle with a gradient.
   if (itemStyle == ItemStyle::separator) {
      const CGFloat colors[][4] = {{0.415f, 0.431f, 0.49f, 1.f}, {0.447f, 0.462f, 0.525f, 1.f}};
      [self fill:rect withContext : ctx withGradient : colors[0]];
   } else {   
      if (!isSelected) {
         CGContextSetRGBFillColor(ctx, 0.415f, 0.431f, 0.49f, 1.f);//CernAPP::childMenuItemFillColor
         CGContextFillRect(ctx, rect);
         
         CGContextSetAllowsAntialiasing(ctx, false);

         //Bright line at the top.
         CGContextSetRGBStrokeColor(ctx, 0.458f, 0.478f, 0.533f, 1.f);
         CGContextMoveToPoint(ctx, 0.f, 1.f);
         CGContextAddLineToPoint(ctx, rect.size.width, 1.f);
         CGContextStrokePath(ctx);
         
         //Dark line at the bottom.
         CGContextSetRGBStrokeColor(ctx, 0.365f, 0.38f, 0.427f, 1.f);
         CGContextMoveToPoint(ctx, 0.f, rect.size.height);
         CGContextAddLineToPoint(ctx, rect.size.width, rect.size.height);
         CGContextStrokePath(ctx);
         
         CGContextSetAllowsAntialiasing(ctx, true);<commit_msg>Fill a separator with a nice gradient.<commit_after>//
//  MenuItemViews.m
//  slide_menu
//
//  Created by <NAME> on 1/7/13.
//  Copyright (c) 2013 <NAME>. All rights reserved.
//

#import <cassert>

#import <QuartzCore/QuartzCore.h>

#import "MenuViewController.h"
#import "MenuItemViews.h"
#import "GUIHelpers.h"

//Menu GUI constants.
//It's a C++, all these constants have
//internal linkage without any 'static',
//and no need for unnamed namespace.
const CGFloat groupMenuItemFontSize = 18.f;
const CGFloat childMenuItemFontSize = 14.f;
NSString * const menuFontName = @"PT Sans";
const CGSize menuTextShadowOffset = CGSizeMake(2.f, 2.f);
const CGFloat menuTextShadowAlpha = 0.5f;
const CGFloat menuItemImageSize = 24.f;//must be square image.
const CGFloat groupMenuItemTextIdent = 10.f;
const CGFloat groupMenuItemTextHeight = 20.f;
const CGFloat childMenuItemTextIdent = 20.f;
const CGFloat childMenuItemTextHeight = 20.f;
const CGFloat discloseTriangleSize = 14.f;
const CGFloat groupMenuItemLeftMargin = 80.f;

using CernAPP::ItemStyle;

@implementation MenuItemView {
   ItemStyle itemStyle;

   //Weak, we do not have to control life time of these objects.
   __weak NSObject<MenuItemProtocol> *menuItem;
   __weak MenuViewController *controller;

   UILabel *itemLabel;
}

@synthesize isSelected;

//________________________________________________________________________________________
- (id) initWithFrame : (CGRect) frame item : (NSObject<MenuItemProtocol> *) anItem
       style : (CernAPP::ItemStyle) aStyle controller : (MenuViewController *) aController
{
   assert(aStyle == ItemStyle::standalone || aStyle == ItemStyle::separator || aStyle == ItemStyle::child &&
          "initWithFrame:item:style:controller:, parameter 'aStyle' is invalid");
   assert(aStyle == ItemStyle::separator || anItem &&
          "initWithFrame:item:style:controller:, parameter 'anItem' is nil and style is not a separator");
   assert(aController != nil && "initWithFrame:item:style:controller:, parameter 'aController' is nil");

   if (self = [super initWithFrame : frame]) {
      menuItem = anItem;
      itemStyle = aStyle;
      controller = aController;
      
      if (aStyle != ItemStyle::separator) {//Separator is simply a blank row in a menu.
         UITapGestureRecognizer * const tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector(handleTap)];
         [tapRecognizer setNumberOfTapsRequired : 1];
         [self addGestureRecognizer : tapRecognizer];
         
         itemLabel = [[UILabel alloc] initWithFrame : CGRect()];
         itemLabel.text = menuItem.itemText;

         UIFont * const font = [UIFont fontWithName : menuFontName size : childMenuItemFontSize];
         assert(font != nil && "initWithFrame:item:style:controller:, font not found");
         itemLabel.font = font;
      
         itemLabel.textAlignment = NSTextAlignmentLeft;
         itemLabel.numberOfLines = 1;
         itemLabel.clipsToBounds = YES;
         itemLabel.backgroundColor = [UIColor clearColor];

         [self addSubview : itemLabel];
      }
      
      isSelected = NO;
   }
   
   return self;
}

//________________________________________________________________________________________
- (void) fill : (CGRect) rect withContext : (CGContextRef) ctx withGradient : (const CGFloat *) gradientColor
{
   assert(ctx != nullptr && "fill:withContext:withGradient:, parameter 'ctx' is null");
   assert(gradientColor != nullptr && "fill:withContext:withGradient:, parameter 'gradientColor' is null");

   CGPoint startPoint = CGPointZero;
   CGPoint endPoint = CGPointMake(0.f, rect.size.height);
      
   //Create a gradient.
   CGColorSpaceRef baseSpace(CGColorSpaceCreateDeviceRGB());
   CGFloat positions[] = {0.f, 1.f};
   //      CGFloat colors[][4] = {{0.f, 0.564f, 0.949f, 1.f}, {0.f, 0.431f, .901, 1.f}};

   CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, gradientColor, positions, 2);
   CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 0);
      
   CGGradientRelease(gradient);
   CGColorSpaceRelease(baseSpace);
}

//________________________________________________________________________________________
- (void) drawFrame : (CGRect) rect withContext : (CGContextRef) ctx
{
   assert(ctx != nullptr && "drawFrame:withContext, parameter 'ctx' is null");

   CGContextSetAllowsAntialiasing(ctx, false);
   //Bright line at the top.
   CGContextSetRGBStrokeColor(ctx, 0.458f, 0.478f, 0.533f, 1.f);
   CGContextMoveToPoint(ctx, 0.f, 1.f);
   CGContextAddLineToPoint(ctx, rect.size.width, 1.f);
   CGContextStrokePath(ctx);
   
   //Dark line at the bottom.
   CGContextSetRGBStrokeColor(ctx, 0.365f, 0.38f, 0.427f, 1.f);
   CGContextMoveToPoint(ctx, 0.f, rect.size.height);
   CGContextAddLineToPoint(ctx, rect.size.width, rect.size.height);
   CGContextStrokePath(ctx);
   
   CGContextSetAllowsAntialiasing(ctx, true);
}

//________________________________________________________________________________________
- (void) drawRect : (CGRect) rect
{
   CGContextRef ctx = UIGraphicsGetCurrentContext();
   
   //For a separator - simply fill a rectangle with a gradient.
   if (itemStyle == ItemStyle::separator) {
      const CGFloat colors[][4] = {{0.447f, 0.462f, 0.525f, 1.f}, {0.215f, 0.231f, 0.29f, 1.f}};
      [self fill : rect withContext : ctx withGradient : colors[0]];
      [self drawFrame : rect withContext : ctx];
   } else {   
      if (!isSelected) {
         CGContextSetRGBFillColor(ctx, 0.415f, 0.431f, 0.49f, 1.f);//CernAPP::childMenuItemFillColor
         CGContextFillRect(ctx, rect);
         
         [self drawFrame : rect withContext : ctx];         
{'fraction_non_alphanumeric': 0.11302543748872451, 'fraction_numerical': 0.02255096518130976, 'mean_word_length': 3.8183398522381573, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4299995', 'n_tokens_mistral': 3635, 'n_tokens_neox': 3281, 'n_words': 826}