New FemCal Feature: Ending a Cycle

Posted by jonathan on December 04, 2011

If you’ve forgotten to enter a later cycle, then FemCal statistics on cycle lengths may indicate longer cycles than is actually the case.

We’ve added a new feature to help correct this.

Ending a cycle in FemCal

New Ending a Cycle Feature

Tap on the left part of the button to let FemCal end the cycle at the default day, usually the day before the start of your next period, or tap on the right to make this the last day of this cycle.

This feature will help FemCal be as accurate as possible when estimating dates for your future cycles.

As always, email us with problems, praise or new suggested features.

FemCal and FemCal Lite Versions 1.9.1 Now Released

Posted by jonathan on October 19, 2011

The iTunes App Store came through and approved the updates to FemCal and FemCal Lite in record time. The issues with entering days with just medications, and with displaying the correct WiFi address for accessing the built-in FemCal web-server have been fixed.

Please sync / backup your devices and update.


bbt, charting, charts, FAM, Fertility Awareness Method, fertility tools, calendars, conception date calculator, fertility calculator, fertility calendar, ovulation, ovulation calculator, ovulation calendar

FemCal 1.9 Bug: Exporting Cycles and Backing-up via WiFi

Posted by jonathan on October 17, 2011

Apologies to anyone having difficulties with downloading PDF cycles, or backing-up data over WiFi. This is due to a bug in FemCal with reporting the wireless address of the iOS device. This occurs under iOS 5.0, but does not otherwise affect the ability to download PDF charts or your information. Only the address to type into your computer browser is reported incorrectly.

There is a suggested work-around available:

  • Set your iPhone to Airplane Mode, then immediately turn on WiFi again. The string to type into your computer browser should then be reported correctly.
  • You may also read the wireless address from the iPhone settings page. Remember to add :8080 to the reported address to access the iPhone FemCal web-page.

The first bullet above is the recommended solution until we can push an update to iTunes.

Note: If you know how to find the wireless address of your iPhone directly, you may also do that. Remember to add port :8080 to the ip address.

Again, our apologies, this will be fixed in the next release. Thanks for your patience.


bbt, charting, charts, FAM, Fertility Awareness Method, fertility tools, calendars, conception date calculator, fertility calculator, fertility calendar, ovulation, ovulation calculator, ovulation calendar

FemCal 1.9 Bug: Saving Days with Just Medications

Posted by jonathan on October 17, 2011

Apologies to anyone who is unable to save days that just include a medication. This is a FemCal bug and will fixed in the next release. No data from previous versions has been lost, though days with just a medication will not be visible right now.

There is a suggested work-around available:

  • For now, enter a note or at least one other piece of data when entering a day for which you only want to enter one or more medications.

Again, no data from previous versions has been lost, as FemCal preserved the previous data files from versions of the app older than version 1.9.

We will fix this bug just as fast as we can, then we will deal with reimporting older data correctly.


bbt, charting, charts, FAM, Fertility Awareness Method, fertility tools, calendars, conception date calculator, fertility calculator, fertility calendar, ovulation, ovulation calculator, ovulation calendar

FemCal 1.9 Now Up On the App Store!

Posted by jonathan on October 14, 2011

FemCal has been received a pretty serious update recently. Here are some of the features that are implemented in this new version 1.9:

  • Support for Apple’s AirPrint. If you have an AirPrint system, supported by your iOS device, then FemCal will be able to print to it.
  • Retina graphics. These are already in FemCal Lite. They are now in FemCal too, including an updated main icon.
  • Improved localization. FemCal will use your localization settings correctly. This includes display of times, dates and numbers. If you write your basal body temperatures like 97,8 then this is now how it will appear in FemCal.
  • Improved cycles page. Your cycles are now all loaded at start-up and available in the cycles menu, and in the download page. You can instantly pick a cycle to chart, or to email, and the your current cycle is always highlighted on the screen in blue text.
  • Improved downloads page. The PDF download page has been improved, with thumbnails of your cycles and a new look.
  • Local backup and restore. You can now export all your information out of FemCal as a single data file, and reenter it at a later date if your iOS device gets reinstalled, or if you get a new device.
  • Gesture support. Swipe up and down on the calendar to move between months. Swipe left and right on the editing page to move between days. This is a great feature if you got behind and need to enter data for several consecutive days.
  • Improved charts. The PDF chart format has been tidied up a little with a lighter look, and better formatting for really long cycles.
  • Better performance. Most areas of FemCal have been improved in performance, whether moving from day to day, or entering your information. We’ve worked hard to give FemCal a more responsive feel.

This is quite a big update, in preparation for even more interesting changes. We hope this will bring some users back to using FemCal, and help more people adopt FemCal as their charting software of choice.

As always, let us know if you have problems, questions, suggestions etc.

Thanks for using FemCal!


bbt, charting, charts, FAM, Fertility Awareness Method, fertility tools, calendars, conception date calculator, fertility calculator, fertility calendar, ovulation, ovulation calculator, ovulation calendar

FemCal Version 1.9 Coming

Posted by jonathan on September 30, 2011

Well, some great news to report. FemCal has been receiving a pretty serious update recently. Here are some of the upcoming features:

  • Support for Apple’s AirPrint. If you have an AirPrint system, supported by your iOS device, then FemCal will be able to print to it.
  • Retina graphics. These are already in FemCal Lite. They are now in FemCal too, including an updated main icon.
  • Improved localization. FemCal will use your localization settings correctly. This includes display of times, dates and numbers. If you write your basal body temperatures like 97,8 then this is now how it will appear in FemCal.
  • Improved cycles page. Your cycles are now all loaded at start-up and available in the cycles menu, and in the download page. You can instantly pick a cycle to chart, or to email, and the your current cycle is always highlighted on the screen in blue text.
  • Improved downloads page. The PDF download page has been improved, with thumbnails of your cycles and a new look.
  • Local backup and restore. You can now export all your information out of FemCal as a single data file, and reenter it at a later date if your iOS device gets reinstalled, or if you get a new device.
  • Gesture support. Swipe up and down on the calendar to move between months. Swipe left and right on the editing page to move between days. This is a great feature if you got behind and need to enter data for several consecutive days.
  • Improved charts. The PDF chart format has been tidied up a little with a lighter look, and better formatting for really long cycles.
  • Better performance. Most areas of FemCal have been improved in performance, whether moving from day to day, or entering your information. We’ve worked hard to give FemCal a more responsive feel.

This is quite a big update, in preparation for even more interesting changes. We hope this will bring some users back to using FemCal, and help more people adopt FemCal as their charting software of choice.

Thanks for using FemCal!

FemCal Ovulation Calendar now has Notes Right on the Chart

Posted by jonathan on July 01, 2010

We’ve had many many requests for this, and we hope you will be happy with it. In fact, we’ve somewhat revised the reports in order to free up space for a notes and procedures section. As of FemCal version 1.8 (waiting for review with Apple) both ‘other procedure’ and ‘notes’ entries will now be included at the bottom of reports.

This works for both current cycles going forward, and for past cycles, so you can go back and generate new reports for past cycles. Here’s an example of the new format:

New FemCal Cycle BBT Chart with Notes and Procedures

New FemCal Cycle BBT Chart with Notes and Procedures

As always, please email us if you have any problems, or if you have ideas for new features.

FemCal Lite and FemCal:Period and Ovulation Calendars Updated 1

Posted by jonathan on June 27, 2010

We recently updated both apps for changes in Apple’s latest iPhones, iPads and iPod Touches.

Aside from the changes needed due to Apple, we’ve also updated FemCal Lite to be able to display the last 90 days worth of data (instead of 60), and changed the charting section to be able to display any of the stored cycles in FemCal Lite. We hope this is useful for folks using FemCal Lite. Write and tell us if it is.

FemCal has been updated to run better on the new iOS 4 on iPhones and iPods, and on iOS 3.2 on the iPad. We are currently working on further updates for FemCal to upgrade the graphics for the fantastic new display on the iPhone 4. We are also working hard to improve how charts are displayed.

FemCal Lite AdHoc Requests – iPhone Period and Ovulation Tracker 3

Posted by jonathan on February 21, 2009

App Store approval seems to be a little on the slow side right now, and I’d like to get some feedback on my latest application FemCal Lite.

FemCal Lite Calendar Display

FemCal Lite Calendar Display

About FemCal Lite

FemCal Lite is the Lite version of FemCal, but still includes all the information that can be entered in FemCal, plus the ability to show a graphical report of your cycles.

The screenshot on the left is the main calendar display from FemCal Lite.

Infertile days are highlighted in red, whilst fertile days are highlighted in green.

The icons displayed on each day include period flow icons, medication, cervical fluid, symptoms and upcoming periods.

You can enter as much data into FemCal Lite as you like, but only the last 60 days is displayed in the calendar. I’d like people to try FemCal Lite and upgrade to FemCal if they like FemCal Lite.



FemCal Lite Screenshots

The following screenshots are taken from FemCal Lite.

Enter Basal Body Temperature

Built-in Help Text

Zoomed in on the Temperature Chart



Requesting an AdHoc Copy of FemCal Lite (Pending App Store Approval)

If you’d like to request a copy of FemCal Lite, please email me the UDID identifier of your iPhone. You can obtain this in iTunes by clicking the text ‘Serial’ until it turns into the word ‘Identifier’. Or you can use Erica Sadun’s utility (free) to email me the identifier. Search the App Store for ‘ad hoc helper udid’.

I’ll update this post when I stop sending out copies. It takes quite a bit of work to generate certificates and generate a working file, so please only ask if you feel that FemCal Lite is of interest.

If you’d like an Ad Hoc copy, send an email with the subject ‘FemCal Lite Ad Hoc Request’ to ‘femcallite@jonathanwatmough.com’, including your UDID. Please follow those instructions exactly. ;-)

Once FemCal Lite is available on the App Store, I’ll update this post.

FemCal Original Version

In the meantime, the version 1.0 of FemCal is available on the App Store.

Click here to visit the iTunes App Store.

Implementing Tap to Zoom in UIScrollView on an iPhone 20

Posted by jonathan on December 11, 2008

I just spent the past two days wrestling with trying to get a working implementation of tap to zoom working correctly in a UIScrollView.

I’m writing an iPhone application that generates a report view, and I really need to allow users to tap to zoom in, tap to zoom out, and still be able to use pinch zooming and panning.

A long search of the Apple demo code, and internet articles did not turn anything definitive up, besides the fact that almost everyone else seems to be having similar problems, including but not limited to: fuzzy renderings when expanding, confused and incorrectly zooming UIScrollViews after manual tap zooming, and much else besides.

I ran into all these problems, and eventually I concluded that the layers underneath a UIView are used to cache zoom renderings, and also carry other state, that it just is not possible to get at through the published api. There *is* a private api, but it is just that, private, and I’d like to get this app on the App Store, so I can’t use it.

Ok, so the approach I created is simply to recreate the scroll view and content view whenever I need to. It turns out that this works well enough for me, both in the simulator, and on the device.

The following is my TapZoomDemo I created to show this solution:

TapZoomAppDelegate.h

//
//  TapZoomDemoAppDelegate.h
//  TapZoomDemo
//
//  Created by Jonathan Watmough on 12/10/08.
//  Copyright __MyCompanyName__ 2008. All rights reserved.
//

#import 

@interface TapZoomDemoAppDelegate : NSObject  
{
    UIWindow *window;
}

// properties
@property (nonatomic, retain) IBOutlet UIWindow *window;

// methods
- (void)createScrollView:(CGRect)scrollFrame contentOffset:(CGPoint)contentOffset contentFrame:(CGRect)contentFrame
           scalingFactor:(float)scalingFactor;


@end

TapZoomAppDelegate.m

//
//  TapZoomDemoAppDelegate.m
//  TapZoomDemo
//
//  Created by Jonathan Watmough on 12/10/08.
//  Copyright __MyCompanyName__ 2008. All rights reserved.
//

#import "TapZoomDemoAppDelegate.h"
#import "MyContentView.h"

@implementation TapZoomDemoAppDelegate

@synthesize window;

// content min and max widths (used to calculate min/max scale factors)
// hardcoded to same as and 2x width of scroll view
static const float kMinWidth = 320;
static const float kMaxWidth = 640;

- (void)dealloc 
{
    [window release];
    [super dealloc];
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Override point for customization after application launch
    
    // put up a backing checked view
    UIView * checks = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
    checks.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"4x4check.png"]];
    [window addSubview:checks];
    
    // use app frame for scroll view
    CGRect scrollFrame = [[UIScreen mainScreen] applicationFrame];
    
    // display our view initially at max size (2x), offset to be centered
    CGRect contentFrame = CGRectMake(0, 0, scrollFrame.size.width*2, scrollFrame.size.height*2);
    CGPoint contentOffset = CGPointMake((contentFrame.size.width-scrollFrame.size.width)/2,
                                        (contentFrame.size.height-scrollFrame.size.height)/2);

    // create scroll view and content view
    [self createScrollView:scrollFrame contentOffset:contentOffset contentFrame:contentFrame scalingFactor:0.0];

    // register for double-tap on content view
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doubleTapZoom:) 
                                                 name:@"DoubleTapZoom" object:nil];
    // bring up app window
    [window makeKeyAndVisible];
}

// helper method for creating a scroll view and content view
- (void)createScrollView:(CGRect)scrollFrame contentOffset:(CGPoint)contentOffset contentFrame:(CGRect)contentFrame
           scalingFactor:(float)scalingFactor
{
    // create content frame at required size, with optional scaling
    MyContentView * content = [[MyContentView alloc] initWithFrame:contentFrame];
    if( scalingFactor!=0 )
        [content setTransform:CGAffineTransformMakeScale(scalingFactor, scalingFactor)];
    
    // create a new scroll view and add to window
    UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
    [window addSubview:scrollView];
    
    // reset min and max scaling
    [scrollView setMinimumZoomScale:kMinWidth/contentFrame.size.width];
    [scrollView setMaximumZoomScale:kMaxWidth/contentFrame.size.width];
    
    // constrain the content offset
    float offsetX = contentOffset.x;
    if( offsetX<0 )
        offsetX = 0;
    if( offsetX>contentFrame.size.width-scrollFrame.size.width )
        offsetX = contentFrame.size.width-scrollFrame.size.width;
    float offsetY = contentOffset.y;
    if( offsetY<0 )
        offsetY = 0;
    if( offsetY>contentFrame.size.height-scrollFrame.size.height )
        offsetY = contentFrame.size.height-scrollFrame.size.height;
    
    // setup the scroll view, size is passed, (possible bad) offset is passed
    // we'll go ahead and use the passed offset, but animate back to constrained
    [scrollView addSubview:content];
    [scrollView setContentSize:contentFrame.size];
    [scrollView setContentOffset:contentOffset];
    [scrollView setDelegate:self];
    
    // be nice and animate back to constrained offset, with optional scaling back to 1.0 (tap zoom)
    [UIView beginAnimations:@"" context:nil];
    [scrollView setContentOffset:CGPointMake(offsetX,offsetY)];
    if( scalingFactor!=0.0 )
        [content setTransform:CGAffineTransformIdentity];
    [UIView commitAnimations];
    
    // rather than cluttering up autorelease pool
    [content release];
    [scrollView release];
}

// scroll delegate methods

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    // return the first subview of the scroll view
    return [scrollView.subviews objectAtIndex:0];
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    // get the view
    UIView * content = [scrollView.subviews objectAtIndex:0];
    
    // get size and offset of (dynamic scaled) content view
    CGPoint contentOffset = [scrollView contentOffset];
    CGSize contentSize = [scrollView contentSize];
    
    // dump the old views
    [content removeFromSuperview];
    [scrollView removeFromSuperview];
    
    // scale the size of the frame to scaled size
    CGRect contentFrame = CGRectMake(0, 0, contentSize.width, contentSize.height);
    
    // create a new scroll view
    CGRect scrollFrame = [[UIScreen mainScreen] applicationFrame];
    
    // create our new content view and containing scroll view
    [self createScrollView:scrollFrame contentOffset:contentOffset contentFrame:contentFrame scalingFactor:0.0];
}

// Double Tap Zoom
- (void)doubleTapZoom:(NSNotification *)notification
{
    // scroll view passed as object, get content subview
    UIScrollView * scrollView = [notification object];
    UIView * content = [[scrollView subviews] objectAtIndex:0];

    // get dictionary holding event, and event
    NSDictionary * dict = [notification userInfo];
    UIEvent * event = [dict objectForKey:@"event"];
    
    // get touch from set of touches for view
    UITouch * touch = [[event touchesForView:content] anyObject];
    
    // need scroll frame, content frame and content offset
    CGRect scrollFrame = scrollView.frame;
    CGRect contentFrame;
    CGPoint contentOffset;

    // zoom in if not at max size, other zoom out to fit to page
    float scalingFactor = 0.0;
    float currentWidth = [content frame].size.width;
    if( currentWidth < kMaxWidth )
    {
        contentFrame = CGRectMake(0, 0, scrollFrame.size.width*2, scrollFrame.size.height*2);
        scalingFactor = kMaxWidth / currentWidth;
        CGPoint touchPoint = [touch locationInView:content];
        contentOffset = CGPointMake(touchPoint.x*scalingFactor/2, touchPoint.y*scalingFactor/2);
    }
    else
    {
        scalingFactor = kMinWidth / currentWidth;
        contentFrame = CGRectMake(0, 0, scrollFrame.size.width, scrollFrame.size.height);
        contentOffset = CGPointMake(0,0);
    }
    
    // dump the old views
    [content removeFromSuperview];
    [scrollView removeFromSuperview];
    
    // create scroll view and content view
    [self createScrollView:scrollFrame contentOffset:contentOffset contentFrame:contentFrame scalingFactor:1.0/scalingFactor];
}

@end

MyContentView.m

//
//  MyContentView.m
//  TapZoomDemo
//
//  Created by Jonathan Watmough on 12/10/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "MyContentView.h"


@implementation MyContentView


- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
        [self setBackgroundColor:[UIColor whiteColor]];
    }
    return self;
}


- (void)drawRect:(CGRect)rect
{
    // Drawing code - This will be called with different bounds at the end of each
    // tap/pinch zoom operation.
    // For illustration, I'm scaling so that a '1' glyph fills the area.

    // context
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Fill view with a 20-point '1'
    UIFont * f = [UIFont systemFontOfSize:20];
    [[UIColor darkGrayColor] set];
    
    // get bounds
    CGRect b = [self bounds];
    
    // draw a string
    NSString * text = @"1";
    CGSize sz = [text sizeWithFont:f];

    // scale to bounds / text size
    CGContextScaleCTM(context, b.size.width/sz.width, b.size.height/sz.height);
    
    // draw
    [text drawAtPoint:CGPointMake(0,0) withFont:f];
}

// look for double taps
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // get any touch
    UITouch * t = [touches anyObject];
    if( [t tapCount]>1 )
    {
        NSDictionary *dict = [NSDictionary dictionaryWithObject:event forKey:@"event"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"DoubleTapZoom" 
                                                            object:[self superview]
                                                          userInfo:dict];
    }
}

- (void)dealloc {
    [super dealloc];
}


@end